ASP.NET Webpart Static Connections - asp.net

I have two webparts in two different webpart zones. They provide a Master/Details scenario using gridviews. They are defined using static connections. Initially this works great.
As soon as I close one of the webparts I get the message "You are about to close the webpart. It is currently providing data to other webparts, and these connections will be deleted if this webpart is closed. Click OK to continue.
This in itself is fine so I click close and my part closes. However when I open the catalog zone and re-add the webpart (which gets added fine) the connection between the parts is broken (as described by the message).
However my webpart connection in my HTML is still visible. I can only assume it uses the ASPNET membership or other to remember the ID of the connection and not to enable it.
My question is how do I re-enable the connection in code or other!?
Thanks.

OK I have solved my issue. I added the following into WebpartManager.WebpartAdded()
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim wp1 As WebPart = zoneDiaryTopLeft.WebParts("Ucl_Diary_Summary1")
Dim wp2 As WebPart = zoneDiaryTopRight.WebParts("Ucl_DiaryAwaitingReview1")
Dim providerConnectionPoint As ProviderConnectionPoint = _
WebPartManager1.GetProviderConnectionPoints(wp1)("IMessageProvider")
Dim consumerConnectionPoint As ConsumerConnectionPoint = _
WebPartManager1.GetConsumerConnectionPoints(wp2)("IMessageConsumer")
Dim returnValue As WebPartConnection
returnValue = WebPartManager1.ConnectWebParts(wp1, providerConnectionPoint, wp2, consumerConnectionPoint)
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
All said, how does it know/store the connection that was removed and remember to NOT allow that to be active!? It would be much easier if I could stop the connection being removed or re-enable it. I know dynamic connections are an option but I dont want users having this ability as they having a hard enough job understanding the fact you can drag a webpart around the screen. Connections are rocketscience to them.

Related

How to store User ID of Logged in User in ASP.net VB.net

I am trying to store the UserId or/and UserName of the user. This is used to record user ID against any changes they make to data, insert, updates and deletes etc.
I have created a module and in that module added a Public variable vUserID. Here Lei the problem.
User A logs in and his id vUserID = 'A'. Another user (User B), the other side of the world logs in User 'B' and that vUserID then = 'B'. So now anything User A does gets recorded as he is User 'B', or that is how I understand it, as a Public variable will be accessible from anyone who logs in.
I understand the problem, or I think I do, please correct me if not, but what I am struggling with is the solution. I have tried to use a Protected and Protected Friend but these do not seem to be accessible throughout the program(website) when a user is logged in.
For completeness I get the User details by the following code which seems to work fine:
Dim mu As System.Web.Security.MembershipUser = System.Web.Security.Membership.GetUser()
Module1.vUserID = mu.ProviderUserKey.ToString()
Well, the issue is that you have ONE web server.
And the web server (for the most part) will process ONE web page at a time.
So, when a user clicks a button on a web page, before they click on a button, the web page is sitting on their desktop computer. it is NOT on the web server.
(and more important, all the code variables (code behind) are GONE! They do not exist yet!).
So, think of a web server as ONE computer. And say 5 users are going to use YOUR computer to edit a word document.
The first user sits down, opens word document, types in some text, and then closes word!
The next user sits down, opens word document, types in some text, and then closes word!
Remember, you don't have a computer for each user, but have ONE computer - the web server, and it has to "some how" service all users.
So, all the web server can do, is "process" a web page, one that is sitting on each end users computer (running the browser).
So, you have this:
And you do NOT have this:
In other words, the web page is NOT sitting "loaded" on the web server. it is out of scope.
Think of when you call a sub, use some variables in that sub, when you return/exit from that sub, ALL VARIABLES are gone!! (out of scope).
You MUST think of web pages like that sub - when you exit, they are gone, don't exist anymore.
So, you don't have this:
the web page is NOT in memory on the server, it is NOT loaded.
Thus, you don't have this either:
So, with above in mind, lets create a super simple web page to show this:
We will have a simple string variable, called MyZooVar.
We will put a button and label on the web page to set this varible.
we will then put another button on the form to show the value of the variable.
So, this:
<asp:Button ID="cmdSetZoo" runat="server" Text="set varable to zoo" />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
<br />
<br />
<asp:Button ID="cmdGetZoo" runat="server" Text="get value of var zoo" />
<asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
and the code behind is this:
Public MyZooVar As String
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Protected Sub cmdSetZoo_Click(sender As Object, e As EventArgs) Handles cmdSetZoo.Click
' set value to variable MyZoovar
MyZooVar = "Hello how are you!"
Label1.Text = "Value of MyZooVar = " & MyZooVar
End Sub
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
Note VERY close in above, the MyZooVar - we defined it at the top of module, so all buttons and code can use that MyZooVar.
So, we will click the first button, this code:
' set value to variable MyZoovar
MyZooVar = "Hello how are you!"
Label1.Text = "Value of MyZooVar = " & MyZooVar
And then we have a 2nd button, and this code:
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
what will happen when we run?
We see this:
So, in above, this is what occured:
we START with this:
You click a button, YOUR web page (not the 20 other users) is sent to the web server.
the page travels up to server,
You now have this:
Now and THEN your code behind runs. When done, your code behind MUST finish, else the page stays stuck up on the server side. When done, the whole page page makes the trip down back to the browser. And THEN the page is re-displayed and THEN any js code can run.
So when done? Your page makes the trip back down to the browser like this:
Note on the server side? Your web code (and MORE important variables) and EVERYTHING is disposed.
We now have this again:
Note HOW THE WEB PAGE IS NOT on the web server!!!!
the web server is waiting now for ANY post-back of a web page from ANY user, not just you the one user!!!!
So, now that I clicked the button to set the variable MyZooVar?
What happens if I click on the 2nd button, this code:
Protected Sub cmdGetZoo_Click(sender As Object, e As EventArgs) Handles cmdGetZoo.Click
' get/show value of zoo var
Label2.Text = "Value of MyZoovar = " & MyZooVar
End Sub
Well, the whole process starts over again!!!
We will find that the variable MyZooVar is gone, out of scope, and does not have our value!!!
So, the "term" for the above is what we call "state-less".
In other words, your code behind can't assume, hope, pray that the varibles in the web page will persit.
Now you can hope/pray/try to put some variables in a global code module, but as you found out, they are shared amoung all users. But WORSE, the web server will often say, hey, I don't need that memory, I'm just sitting here waiting for someone to click a button and send me THEIR web page.
As a result, not only will you find those so called global variables in that public code module shared between all users, you find that they OFTEN will not even stay in memory all that long. So, your code "sort of works" to try and use some global variables, but you find they OFTEN go out of scope, and will not even stay in memory.
So, web based software is VERY different then desktop software.
One big difference is that for desktop software, each user, each workstation has their OWN copy of the code.
With a web server, you have ONE web server, ONE computer, and it sole job is to process incoming web pages (that occurs due to a page post-back).
the process of a simple button click, whole web page travel up to web server, page is processed, and then whole page is send back to user? We call this a round trip.
So, you really do not have global variables in a web based application. You can try to use some, but as noted, they will be the same for all users, but MUCH worse, is they tend to go out of scope, and can be disposed (go away) at any old time - you have no control over this, and thus you simple can't adopt global variables in a web based system - they are "off limits", and the above so called round tripping, and that you have ONE computer and ONE web site that somehow has to service many users - not just you!!
So, in your case?
Why do you need to store/save the user ID in some variable?
You "already" are able to get the user id with the code you shared:
You can use this:
dim UserID as integer
UserID = Membership.GetUser().ProviderUserKey
So, since you can get the "user" id any old time with above ProviderUserKey, then no need exists to try and "save" the user id into some global variable, but as you found out, you can't rely, or even design your software based around a concept of global variables.
However, you can if you wish place values into what we call "session".
Session is in effect global to the ONE user, and it DOES persist between those so called round trips.
so, you could do this:
Session("MyUserID") = Membership.GetUser().ProviderUserKey
And then in code, any time, use
Session("MyUserID") to get the user "id"
But, since you have ProviderUserKey, then even session() should not be required here.

Loosing session variable data from one page to the other in VB.NET

I am a bit new to VB.NET. I have a page that sets 2 session variables and does a redirect to second page. The second pages is at least using one of the session variables. I can tell because on the second page, if the session variable is not correct the user is redirected to an access denied page. The second page also uses the session variable in question. It will read it an fill a gridview based on the value of the variable. I set the variable like so
Session("ID") = Convert.ToInt32(a_value)
and on the second page I retrieve the variable like this
a_page_variable = Session("ID")
What I find strange is that when I run this code in visual studio it works as expected but when I deploy and run it, I get 0 from my session variable instead of the true value of "a_value". I have tried a few things like making sure the data types match up from page to page and trying different ways to retrieve the variable such as
Session("userID")
and
CType(Session.Item("userID"), Int32)
I've also tried to see what is coming in to the second page by using
Response.Write
I also tried to use SQL Profiler to see what kind of call is being made to fill the gridview but I haven't had any luck. The gridview gives me an empty dataset and the Profiler does not detect a call being made from the application. I thought working with session variables was pretty straight forward but obviously, I am missing something.
Thanks for your help,
Billy
One possibility (and the only one that could be guessed at with how little information we have) could be the response.redirect causing the application to terminate due to an exception.
When redirecting, you want to always pass a false, and then call complete request.
Response.Redirect(urlstring, False)
Response.CompleteRequest()
not following these steps can cause exceptions, which may drop session.
Additionally, resolve virtual paths, as some browsers (mobile especially) can see those redirects as new requests entirely, thus generating new session tokens.
Dim urlstring As String
urlstring = Page.ResolveUrl("~/default.aspx")
that said, there are a number of possible causes for this situation.
Application Pool restarts
App Domain restarted
Code changing value unexpectedly
AV tinkering with files
deployed to web farm
With the description provided above, we just don't have enough information to really troubleshoot.
Thank you ADyson, Stephen Wrighton and everyone else who took a stab at helping me figure this out. I was able to find out what was going on by adding code that wrote to a log file on the server. Found the logging code here. I found that I never reached the code that set the session variable and that is the reason it never populated on the second page. I was trying to get the logon name for the user by using Environment.UserName which will return the user name of the person who is currently logged on to the operating system. But what I really wanted to do was get the logon name of the user that was visiting my site. For this I used User.Identity.Name. This works great when you need to know which user from an Active Directory domain is visiting your site.

ASP.NET modify connectionstring at runtime

I need to change dataset connectionstrings to point to different DBs at run time.
I've looked at a number of solutions however they all seem to be related to WinForms or web application projects or other technology slightly different than what I'm using, so I haven't figured out how apply them.
The application is like a discussion. It's a web site project based on code originally written under VS2005, and there's no budget (or personal talent!) for major changes at this time. The app is written in vb.net; I can understand answers in c#. I'm working in VS2013.
The app has three typed datasets pointing to one MDF, call it "MainDB.mdf". There are dozens of tableadapters among the three datasets.
I'm going to deploy the app it as an "alpha/demo" version. I would like to use the same code base for all users, and a separate physical version of MainDB for each user, to reduce chances that the users crash each other.
The initial demo access URL will contain query string information that I can use to connect the user with the right physical database file. I should be able to identify the database name and thus the connection string parameters from the query string information (probably using replace on a generic connection string). If necessary I could use appsettings to store fully formed connection strings, however, I would like to avoid that.
I would like to be able to change the connection strings for all the datasets at the time that the entry point pages for the app are accessed.
Changing the tableadapter connection strings at each instantiation of the tableapters would require too much code change (at least a couple of hundred instantiations); I'd just make complete separate sites instead of doing that. That's the fall back position if I can't dynamically change the connectionstrings at runtime (or learn some other way to make this general scheme work).
Any suggestions on how to approach this would be appreciated.
Thanks!
UPDATE: Per comments, here is a sample instantiation of tableadapter
Public Shared Sub ClearOperCntrlIfHasThisStaff( _
varSesnID As Integer, varWrkprID As Integer)
Dim TA As GSD_DataSetTableAdapters.OPER_CNTRLTableAdapter
Dim DR As GSD_DataSet.OPER_CNTRLRow
DR = DB.GetOperCntrlRowBySesnID(varSesnID)
If IsNothing(DR) Then
Exit Sub
End If
If DR.AField = varWrkprID Then
DR.AField = -1
TA.Update(DR)
DR.AcceptChanges()
End If
End Sub
UPDATE: Below is the test code I tried in a test site to modify the connectionString in a single instantiation of a tableadapter. It feeds a simple gridview. I tried calling this from Page_Load, Page_PreLoad, ObjectDataSource_Init, and Gridview_Databind. At the concluding response.writes, the wrkNewConnString looks changed to TestDB2, and the TA.Connection.ConnectionString value looks changed to TestDB2, but the displayed gridview data is still from TestDB1. Maybe it needs to be called from somewhere else?
Sub ChangeTableAdapter()
Dim wrkNewConnStr As String = ""
Dim wrkSel As Integer
wrkSel = 2
wrkNewConnStr = wrkNewConnStr & "Data Source=.\SQLEXPRESS;"
wrkNewConnStr = wrkNewConnStr & "AttachDbFilename=D:\9000_TestSite\App_Data\TESTDB1.MDF;Integrated Security=True;User Instance=True"
Select Case wrkSel
Case 1
wrkNewConnStr = wrkNewConnStr.Replace("TESTDB1", "TESTDB1")
Case 2
wrkNewConnStr = wrkNewConnStr.Replace("TESTDB1", "TESTDB2")
Case 3
wrkNewConnStr = "Data Source=localhost; Initial Catalog=test01;"
wrkNewConnStr = wrkNewConnStr & " User ID=testuser1; Password=testuserpw1"
End Select
Try
Dim TA As New DataSetTableAdapters.NamesTableAdapter
TA.Connection.ConnectionString = wrkNewConnStr
Response.Write("1 - " & wrkNewConnStr)
Response.Write("<br/>")
Response.Write("2 - " & TA.Connection.ConnectionString)
Catch ex As Exception
Dim exmsg As String = ex.Message
Response.Write(exmsg)
End Try
End Sub
The connection string:
<add name="TestDB1ConnectionString"
connectionString="Data Source=.\SQLEXPRESS;
AttachDbFilename=D:\9000_TestSite\App_Data\TESTDB1.MDF;Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
UPDATE: the following post has lots of solutions, however, they seem to focus on web application projects, that have a project file with settings, which this web site project does not.
link with possible solutions
UPDATE: this next link was brought to my attention, and in working on it I did get it to work, however, it still relies either on having a web application project (with project file) or modifying each table adapter as they are instantiated. So, while I'm not going to implement it, I believe that is the technical answer.
modifying connection strings
sorry if this answer is too late, but I have exactly the same problem and eventually came up with a solution using Reflection.
My solution was to "save" a new default value for the connection string in the settings at run time, which means any further use of the table adapter uses the the new connection string.
It should be noted the term "save" is misleading as the new value is lost when the application closes.
Have tested and worked perfectly.
public void ChangeDefaultSetting(string name, string value)
{
if (name == null)
throw new ArgumentNullException("name");
if (value == null)
throw new ArgumentNullException("value");
Assembly a = typeof({Put the name of a class in the same assembly as your settings class here}).Assembly;
Type t = a.GetType("{Put the full name of your settings class here}");
PropertyInfo propertyInfo = t.GetProperty("Default");
System.Configuration.ApplicationSettingsBase def = propertyInfo.GetValue(null) as System.Configuration.ApplicationSettingsBase;
//change the "defalt" value and save it to memory
def[name] = value;
def.Save();
}

Execute VB Script on page_load

I am having VB Script in ASPX page.I need to use that Script in codeBehind in Page _load with in a For loop,for each iteration.
My Code is :-
(.ASPX Page with VB Script. )
<script type="text/vbscript" language="vbscript" >
sub wordit()
'Opens Word application and does some process
end sub
</script>
VB Code Behind Part:-
For i As Integer = 1 To colSelRowIndex
CheckboxTemplateId = colSelRowKeys(i).ToString 'I get the ID from here
ViewState("TemplateID") = CheckboxTemplateId 'I need to send the value to the sub routines
hen()'sub
den()'sub
cs.RegisterStartupScript(cstype, csname1 & i, "wordit();", True)
Next
I need to open a word doc for an ID and another document for another ID from the loop.
Try this:
For i As Integer = 1 To 10
cs.RegisterStartupScript(cstype, csname1 & i, "wordit();", True)
Next
That second argument in that function call is looking for a unique key. This is a feature, to prevent accidentally programmatically adding the same script more than once. If you want to do it on purpose, you need a unique key each time.
But that you want to do this at all indicates a possible fundamental misunderstanding about what's going on. While your server code (including Page_Load) is running, your client page in the web browser doesn't exist. The purpose of the server code is always to generate an html response to web request. The server code can never directly manipulate a page DOM.
Obviously this is true for a first request to a page in session: the server must first generate the initial page to send the client. But even on subsequent postbacks, the browser will destroy the prior instance of a page. The server must rebuild the entire page from scratch. Every. Time. While this happens, the page you're looking at in your browser window is only a sort of after-image. The browser has already destroyed any prior DOM, and is waiting for the server to supply a whole new set of HTML.
I also wonder at your use of vbscript, rather than javascript. Using vbscript pretty much guarantees you're page will only work with Internet Explorer.

What's the best way to display an image from a sql server database in asp.net?

I have a sql server database that returns byte for the image. If I use the tableadapter wizard and set it to my stored procedure and preview data, it pulls back an image. It automatically turns it into an image in the preview data. I don't see it as a string of Ints or anything.
How can I display it on my asp.net webpage with a gridview and objectdatasource?
I have searched and foudn where the imagefield can point to a url on another page that does the byte transformation but I'm not sure it's the best. I found another way that creates a temp file.
Just trying to see the best way to do it.
edit - I am trying not to use a temp file. If I cannot use a gridview a regular image field is ok.
asp.net 2.0, c#.
Thank you for any help.
edit
ended up with:
protected void Page_Load(object sender, EventArgs e)
{
string id = Request["id"];
string connstr = "DSN=myserver";
OdbcConnection conn = new OdbcConnection(connstr);
OdbcCommand cmd = new OdbcCommand("{call mySP (?)}", conn);
cmd.CommandType = CommandType.StoredProcedure;
// Add the input parameter and set its properties.
OdbcParameter parameter = new OdbcParameter();
parameter.ParameterName = "#MyParam";
parameter.OdbcType = OdbcType.VarChar;
parameter.Direction = ParameterDirection.Input;
parameter.Value = id;
// Add the parameter to the Parameters collection.
cmd.Parameters.Add(parameter);
conn.Open();
OdbcDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
byte[] buffer = (byte[])dr[0];
Response.ContentType = "image/jpg";
Response.BinaryWrite(buffer);
Response.Flush();
}
}
and this on the calling page:
<asp:Image ID="Image1" ImageAlign="Middle" ImageUrl="show.aspx?id=123" Runat="server" />
Two options:
Create a temp file - The problem with this approach is that you have to create the file, which means your web must have write access to a directory which is not a great thing. You also need to have a way to clean up the images.
Serve it from another URL - This is my preferred method, as you have no disk access required. A simple http handler (ashx) is a great method to serve up the image.
Edit
If you need session state in the ashx, check out: Asp.net System.Web.HttpContext.Current.Session null in global.asax.
Edit
Couple more thoughts. There are some cases where using a temp file might be better. For example if your images are requested frequently by a lot of users. Then storing the images on the disk would make sense, since you could write the file once, this does increase the maintance complexity but depending on traffic it might be worth it since this would let you avoid calling back into the .net stack and leverage IIS caching of static content.
I wrote the SqlReader plugin for open-source ImageResizing.Net library to allow you to serve and display images from a SQL database in the most performance-optimal way.
Even if you don't need to do any image processing whatsoever, it's still (a) the easiest, and (b) the most efficient way to do it. You can combine it with disk caching (which provides automatic cleanup) to get the best performance that is possible.
Installation is easy - 2 nuget commands, or copy & paste into Web.Config, your pick.
If you need help, support is free and fast.
The sample code you added is good but you should move it to a .ashx file which is meant for such things.
Here is some example code on how to do this.

Resources