Tuesday, December 9, 2008

Passing Values between user controls using Events and Delegates


Always there comes a requirement where we developers need to pass values to between different user controls which are parts of a webpage or even sometimes there comes a requirement where we need to pass values from user control to the container page.
The job is easy when we have to pass values which are there on the user controls by exposing the value fields as properties of the user control. However it is challenging when on certain event the values should get passed.


The simplest solution to this situation I found is to handle this by use of events and delegates. Let me explain the solution with one simple example.
For example on a content page I am having two user controls e.g. UC1 and UC2. Contents of UC1 are:
1. List box having list of States
2. List box having list of Cities in the State (Pre-condition: User selects State from ListBoxStates and respective cities in the selected state gets populated in the ListBoxCities)
3. Button control, which will be used for confirming the user’s selections. Let us name it as btnSelect.
Contents of UC2 are:
1. List of selected cities from UC1. Let us name it as ListBoxSelectedCities.
Our requirement is whenever user selects (multiple) cities from ListBoxCities and clicks on btnSelect in UC1 then the selected cities should get populated in ListBoxSelectedCities in UC2.

In UC1, we need to declare the following objects:

public delegate void PassSelectedValues(string[] selectedCities);

public event PassSelectedValues citiesSelected;

Now in UC1 from the button click event we can raise citiesSelected event, delegate of which will carry the required values which we need to pass in between UC1 and UC2. In button click event we have to create the list of selected cities from ListBoxCities and we have to raise the citiesSelected event like this:


Here selectedCities is an array of strings which we have to create by looping through the ListBoxCities.

We have to declare a public property in UC2 which can be used to set the ListBoxSelectedCities. For example in UC2:

public string[] SelectedCitiesList




ListBoxSelectedCities.DataSource = value;




In the content page we have to declare the event handler for the event (citiesSelected) which we have raised from UC1. Thus in content page on page load we have to declare the handler of this event like this:

UC1.citiesSelected += new citiesUserControl.PassSelectedValues(passValuesHandlerMethod);

This handler method in the content page should have the same signature as of the delegate’s signature defined in UC1.

protected void passValuesHandlerMethod(string[] selectedCities)



Now from this method we can pass the value coming from UC1 to UC2 like this:

protected void passValuesHandlerMethod(string[] selectedCities)


UC2.SelectedCitiesList = selectedCities;


In this way whichever values we are selecting in UC1 will get passed to UC2.


In this article we have seen that how to pass values between different user controls on a webpage using events and delegates. Same concept can be applied for passing value from user control to the content page.

Hope this will help everyone in handling their cases.




Tuesday, November 25, 2008

Session maintenance using SQL Server for .Net Web applications

I am listing all the steps how to configure the SQL Server so that our .Net application can store and retrieve the Session values in and from SQL server. All suggestions for improvement are heartly welcome.
Session maintenance in SQL Server for .Net Applications:
1. Run aspnet_regsql.exe from .Net command prompt. This will run a wizard.
2. Provide server name
3. Use windows authentication if you are having rights to create tables on your server else provide the sys admin user name and password
4. Use the AspState database
5. This will create set of tables in AspState and tempdb databases
6. Create logins for the application user on AspState and tempdb databases
7. Execute the following script:
use APSState
grant EXECUTE on GetHashCode to [user]
grant EXECUTE on GetMajorVersion to [user]
grant EXECUTE on TempGetAppID to [user]
grant EXECUTE on TempGetStateItem to [user]
grant EXECUTE on TempGetStateItem2 to [user]
grant EXECUTE on TempGetStateItem3 to [user]
grant EXECUTE on TempGetStateItemExclusive to [user]
grant EXECUTE on TempGetStateItemExclusive2 to [user]
grant EXECUTE on TempGetStateItemExclusive3 to [user]
grant EXECUTE on TempGetVersion to [user]
grant EXECUTE on TempInsertStateItemLong to [user]
grant EXECUTE on TempInsertStateItemShort to [user]
grant EXECUTE on TempInsertUninitializedItem to [user]
grant EXECUTE on TempReleaseStateItemExclusive to [user]
grant EXECUTE on TempRemoveStateItem to [user]
grant EXECUTE on TempResetTimeout to [user]
grant EXECUTE on TempUpdateStateItemLong to [user]
grant EXECUTE on TempUpdateStateItemLongNullShort to [user]
grant EXECUTE on TempUpdateStateItemShort to [user]
grant EXECUTE on TempUpdateStateItemShortNullLong to [user]
grant SELECT on ASPStateTempApplications to [user]
grant INSERT on ASPStateTempApplications to [user]
grant UPDATE on ASPStateTempApplications to [user]
grant SELECT on ASPStateTempSessions to [user]
grant INSERT on ASPStateTempSessions to [user]
grant UPDATE on ASPStateTempSessions to [user]

use tempdb
grant SELECT on ASPStateTempApplications to [user]
grant INSERT on ASPStateTempApplications to [user]
grant UPDATE on ASPStateTempApplications to [user]
grant SELECT on ASPStateTempSessions to [user]
grant INSERT on ASPStateTempSessions to [user]
grant UPDATE on ASPStateTempSessions to [user]

8. Do the following changes in Web.Config file:
allowCustomSqlDatabase="true" cookieless="false" timeout="20"/>
9. Make sure that all classes in the application, whose objects we are storing in Session, should have the [Serializable] attribute.
Now few points:
  1. We can store huge data in Session without effecting the Web server momory.
  2. We are shifting the burden of runtime memory to SQL database. So that we can now create the application which can handle huge Session data.
  3. Minus point is that every Session request will be redirected to DB Server from Web Server.

Friday, June 13, 2008

Limiting File Upload Sizes with ASP.NET

User can upload images of any arbitrary size. This is not good for either network traffic or database size, and raises the possibility of a nasty denial of service attack. So, the next step is to limit the uploaded file size to a reasonable value. The customer chose 128K as their maximum image size.
Your first thought might be to check the ContentLength property of the uploaded file to see if it's within the expected size, and to bail out of the procedure if it's too large. Unfortunately, this is only half of a solution. While that check would prevent the file from getting to the SQL Server database, it still requires the entire file to be uploaded first, potentially clogging the network. Fortunately, ASP.NET provides a better solution
It turns out that you can add a tag to the Web.Config file to specify a maximum size for uploaded files.

The maxRequestLength attribute of the httpRuntime tag specifies, in KB, the largest HTTP request that the application will accept. The default is 4096 KB, which is a little large for most applications. Be careful about setting this too low, though, as it applies to every request, not just uploaded files. If you're moving a lot of data around in ViewState, for example, you could run afoul of a too-low setting.
With this change to the Web.Config file, large files won't even be accepted by the server. But the user experience could use some work. What happens if the user tries to upload a large image with this setting in place:
ASP.NET rejects the request in the rudest way possible, telling the client that there's no such page.
Telling the User What Happened
To get a better error message across to the user, you need to turn to another corner of the application. If your first impulse is to put a Try/Catch block in the page load to catch the error, think again: ASP.NET doesn't load the page at all in this situation. You have to move up the processing chain to the error event in the global.asax.vb file, which is called for every error in the application.
The strategy I settled on was to catch the error, and then redirect the user back to the original page with an error message. That way, they'll get a chance to try again with a different file. To start the process, I added some code to the global.asax.vb file:

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' Fires when an error occurs
' Check to see whether we came
' from the upload form
If Path.GetFileName(Request.Path) = "UploadForm.aspx" Then
' Get the error details
Dim appException As System.Exception = Server.GetLastError()
Dim checkException As HttpException = CType(appException, HttpException)
' Verify the expected error
If checkException.GetHttpCode = 400 And checkException.ErrorCode = -2147467259
' Error 400 = bad request, user
' tried to upload a file that's too large
Session("ImageTooLarge") = True
' Go to the original target page
End If
End If
' For other errors, just accept the default processing
End Sub

The next step was to add a label control to the original upload form. The control's name is lblTooLarge, its text is a warning that the image is too large, and its Visible property is set to False. Then I modified the Page_Load procedure of the upload form:
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not IsPostBack Then
' Check to see whether we were redirected
' from the error page
If Session("ImageTooLarge") = True Then
lblTooLarge.Visible = True
Exit Sub
End If
' Get the uploaded data
Dim upfile As HttpPostedFile = UploadFile.PostedFile
' Remaining code unchanged ...
End If
End Sub

If the user tries to upload a file, the error gets caught in the global.asax file. At that point, the code retrieves the error details and verifies that this is the error that happened; I don't assume that it's the only possible error in the application! If it is, the code sets a flag in the session state and hands control back to the upload form. The upload form checks for the flag and makes the label visible so that the user will know what they did wrong.

Wednesday, March 12, 2008

The pace of updating technologies

With the Beta release of Framework 3.5, Microsoft is boasting of another big achievement.

I do not know about other developers but as I am one of the developer who works on MS technologies is finding it difficult to keep the same pace of updating myself with the new frequent releases. Although MS is bringing a revolutionary change in its own technology but MS should also consider about the users of MS technologies also.

But the good thing is that MS seems to be realized this and they have started providing free session on the upcoming tech releases. However I do not think that this is all what MS can do. They can really give a substantial pause to the new releases so that all the developers like me who are interested in knowing the technology from start to end, will get proper time to update themselves in the existing technologies rather than jumping from one release paper to another. Thanks.

Please post your valuable comments on this.