View the data that LoadPostData event is loading in ASP.NET - asp.net

What's the best way to view the data that LoadPostData event is loading to the controls in ASP.NET?

It's actually really simple. The NameValueCollection that get's passed to this method of EVERY control that implements the IPostbackDataHandler interface is the contents of Page.Request.Form. So you can access it at any time by getting a Watch on HttpContext.Current.Request.Form.

Ugh... I would suggest setting your IDE environment up to debug the .net framework, and set a breakpoint on the LoadPostData() method of Control. That's a bit heavy-handed, but if you're willing to wade through the recursive calls to the Control class (perhaps set a conditional breakpoint on the method?), you will be able to get to the data that way.
Good luck!

If you want to be sure you're looking at the data going into a particular control, you can subclass its control type and break during a custom implementation of IPostBackDataHandler.LoadPostData.
For example, you have a programmatically added control to collect the user's city. Change:
Public City As Textbox
to
Public City As BreakableLoadPostDataTextBox
Public Class BreakableLoadPostDataTextBox
Inherits TextBox
Protected Overrides Function LoadPostData( _
ByVal postDataKey As String, _
ByVal postCollection As System.Collections.Specialized.NameValueCollection) _
As Boolean
Return MyBase.LoadPostData(postDataKey, postCollection) ' Break here
End Function
End Class
Set a breakpoint on the Return call. When execution breaks, you should be able to see the postDataKey that's being used to read the control's new value out of the postCollection. You can of course augment this method to your heart's content with Trace calls and whatnot.

Related

VB.Net: call sub from shared sub

I have some Ajax on a web page that feeds some data to a server-side VB.Net method. Once that data is in the server-side method, I need to call another server-side method to use the data I just collected. Here is a really simplified example:
' This method gets the input from the Ajax code on the web page.
<System.Web.Services.WebMethod> _
Public Shared Sub GetAwesome(VBInputText As String)
Dim strTest As String = VBInputText
' Now that we have collected input from the user,
' we need to run a method that does a ton of other stuff.
DisplayAwesome(VBInputText)
End Sub
Protected Sub DisplayAwesome(AwesomeIn As String)
' The real app does a lot more than this. For this example, it
' just sets the text of a literal.
litAwesomeResult.Text = AwesomeIn
End Sub
Of course, in the above example DisplayAwesome(VBInputText) gives me the 'Cannot refer to an instance member...' error. So, is it possible now to call Protected Sub DisplayAwesome from Public Shared Sub GetAwesome? I'm hoping to stay close to this sort of solution because it would play very well with the app as it is already written by another coworker.
unfortunately you cannot do this, Since the page method DisplayAwesome is defined as Protected and you requires an instance of the class to access the Protected method. But changes in another instance will not reflect in the current UI. another thing you can do is Make DisplayAwesome as Shared, but this time you cannot access the UI elements inside the shared function.
The thing you can do in this situation is, return data to the called method(in front end) and handle the litAwesomeResult.Text there
Call sub with name of Form Class like this:
FormName.DisplayAwesome(VBInputText)
In VB.Net, you can call the method not shared from a shared method with Name of Form Class by default instance, because The default instance is an object Form type that the VB application framework create and manage it, when the form is added to the project.
For more info see this :
VB.NET Default Form Instances

Storing and restoring properties in ASP.NET derived control

I have created an ASP.NET class derived from the standard WebControls.TextBox, with the intention of adding extra properties that will persist between post-backs. However, I cannot figure how to get the values in these properties to persist.
I have tried setting the value of the properties into the controls ViewState as part of the PreRender handler, but the value is then not accessible in the Init handler on the post-back, because the ViewState has not yet been setup.
I could look for the ViewState value in the Load handler of the control, but if the page/usercontrol that is using the control asks for the properties value during its Load handler, the control hasn't yet reached it's Load handler, and it therefore not there.
My current class looks something like this...
Public Class MyTextBox
Inherits TextBox
Private _myParam As String = ""
Public Property MyParam As String
Get
Return _myParam
End Get
Set(value As String)
_myParam = value
End Set
End Property
Private Sub MyTextBox_Init(sender As Object, e As EventArgs) Handles Me.Init
If Page.IsPostBack Then
_myParam = ViewState("myParam")
End If
End Sub
Private Sub MyTextBox_PreRender(sender As Object, e As EventArgs) Handles Me.PreRender
ViewState("myParam") = _myParam
End Sub
End Class
I must be missing something really simple, such as whether there is an attribute I can set against the property.
UPDATE
Thanks to #AVD pointing out that I really had very little clue about the ViewState and the Init / Load stages, I finally figured it all out.
If you have the time (and if you're doing any major ASP.NET work, you need to make the time) please read the Understand ASP.NET View State document that #AVD pointed me to. It will explain a lot.
However, what it didn't explain is if you place your control within a <asp:Repeater>, you may as well throw all the rules out of the window... and that is exactly the problem I was experiencing.
In the end, the way I managed to get it to work was to use a <asp:PlaceHolder> control within the repeater, create an instance of my control within the ItemDataBound handler of the repeater, and then add the control to the <asp:PlaceHolder>... all done within the Init section (which fortunately I'm able to do).
As Andrew found out in this previous question you can end up in a chicken/egg situation, where you need to create the controls in the Init, but you won't know what controls you need until the Load.
(I have still made AVD's answer the correct one, because in the context of my original question, it is absolutely correct).
You have to store/retrieve value to/from ViewState within the properties accessors.
Public Property MyParam As String
Get
If IsNothing(ViewState("myParam")) Then
return string.Empty
End IF
Return ViewState("myParam").ToString()
End Get
Set(value As String)
ViewState("myParam") = value
End Set
End Property

Can't get Session variable the way I want to

Partial Class Preferences_MyPreferences
Inherits System.Web.UI.Page
Dim userID As String = Session("UserID")
This is just a page in asp.net. I want to be able to grab the Session("UserID") but every time I try, I get this error:
Session state can only be used when enableSessionState is set to true, either in a configuration file or in the Page directive. Please also make sure that System.Web.SessionStateModule or a custom session state module is included in the \\ section in the application configuration.
If I put that Dim userID inside say the Page_Load Event, then it works fine. Why does it have to be inside an event? I want to dim it once, and use it throughout the page.
Consider wrapping your call to the Session in a property in your code behind?
Public ReadOnly Property UserID() As String
Get
Return Session("UserID")
End Get
End Property
If you declare it as you have there, the variable is initialized and the session variable is expected to be ready for usage, but it is too early in the page life cycle to allow that. The preferred method would be as #p.campbell has suggested and wrap it in a Property or similar method. To answer the question though, the exception is generated because you are attempting to use session before it is available.
You need to read up on ASP.NET Page Lifecycles. The Session object doesn't become available until a certain point in the page lifecycle; if you want to grab the UserID once, you need to do it after the session becomes available.
The reason it doesn't work in your example is that the constructor for your Preferences_MyPreferences page is executed before the request object is available to the page. You should instead load it during the Page_Init or Page_Load event.

Extending ASP.NET validators

I want to extend the asp.net validators such that I can make one validator dependent on another. The situation I have is that we have to validate a date in a textbox. Normally I would just use a combination of a RequiredFieldValidator (to ensure the date is provided), CompareValidator (to ensure the date is a date) and finally a RangeValidator (to ensure the date is within the required limit).
The problem with this is that the validators do not depend on each other, so as a result the user would see possibly all three messages at once for each validator when really all we want them to see is the most relevant message, i.e. if they entered "abc" in the date text box it would not be appropriate to show them the message saying the date was not in the valid range (even though technically I suppose this is true).
Currently to provide this kind of functionality we use a CustomValidator and just put all three validations within the server validate event handler and change the error message programmatically depending on what validation failed.
I would like to standardize this a bit more as it happens quite a bit in this application, I figure if I can make the validators dependent on each other this will solve the problem and also allow us to make use of the client side validation rather than having to do a postback especially to handle the custom validation.
The idea is that if one validator is dependent on another if that "master" is valid then the depended will perform its normal validation (EvaluateIsValid()) otherwise if the master validator is not valid then the other dependent validators will be valid.
I have come up with the following solution by inheriting from the various validator controls that already have been provided in the framework.
public class RequiredFieldDependentValidator : RequiredFieldValidator
{
[Description("The validation control to depend on for determining if validation should occur")]
public string ValidationControlToDependOn
{
get
{
object obj = ViewState["ValidationControlToDependOn"];
if (obj != null) return (string) obj;
return null;
}
set
{
Control control = FindControl(value);
if (control is IValidator)
ViewState["ValidationControlToDependOn"] = value;
else
throw new HttpException("ValidationControlToDependOn is not a validation control");
}
}
protected override bool EvaluateIsValid()
{
IValidator validationControlToDependOn = FindControl(ValidationControlToDependOn) as IValidator;
if(validationControlToDependOn != null)
{
return !validationControlToDependOn.IsValid || base.EvaluateIsValid();
}
return base.EvaluateIsValid();
}
Currently I have just coded it for the RequiredFieldValidator, ideally I would like to provide this functionality for all of the validators but I cannot see a way to do this without copying the above code into a similar class for each individual type of validator I want to provide this functionality for thus if there are any problems I'm going to have to go back and change this code on each validator type individually.
Is there a way I can "centralise" this code and have it easily used in the validators without having to write the entire validators from scratch just so I can change the class they inherit from further down the line.
Cheers,
You could override the Validate method in you page base. To add the validation dependency information in the page you can implement a not rendered control:
<my:ValidationDependency TargetControl="RegExp1" Dependency="Required1" />
You might want to look into a WebControlAdapter.
Basically allows you to override certain methods of webcontrols (conditionally for some browsers if need, but here can be for all).
In your case, you would want to override the EvaluateIsValid method and check if the control has any dependency on a 'parent' validator.
As an example, a TextBox adapter we recently created to render a 'maxlength' attribute to the control.
Public Class TextBoxAdapter
Inherits WebControlAdapter
Private ReadOnly Property TextBoxControl() As TextBox
Get
Return DirectCast(MyBase.Control, TextBox)
End Get
End Property
Protected Overrides Sub RenderBeginTag(ByVal writer As System.Web.UI.HtmlTextWriter)
If TextBoxControl.TextMode = TextBoxMode.MultiLine AndAlso TextBoxControl.MaxLength > 0 Then
writer.AddAttribute("maxlength", TextBoxControl.MaxLength.ToString)
End If
MyBase.RenderBeginTag(writer)
End Sub
End Class
To use it, just create a .browser file in your App_Browsers directory and setup the adapter there:
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.TextBox"
adapterType="TextBoxAdapter" />
</controlAdapters>
</browser>
</browsers>
The only complication that still remains in your case is how to store the dependent validator in order for the EvaluateIsValid to have access to this directory. You might consider a non-rendered control like Onof suggested or else Viewstate/Cookie/other storage mechanism.
you can have ValidationControlToDependOn property as of type List and add the validators into the list. So we can assume that the validator added later depends upon the validator added before it.
so your protected override bool EvaluateIsValid()
will change somewhat
foreach(IValidator validator in ValidationControlToDependOn)
{
return !validator.IsValid;
}
I'm looking into control extenders which seems like it could be promising but I cannot find many examples of doing anything but AJAX stuff with it.

Passing Parameters to New Sub of a User Control

In ASP.Net, is it possible to pass parameters to the "New" constructor of a User Control class? In VB.Net:
Public Sub New(ByVal pRequiredParam As String)
'Do something with required Param
End Sub
When I use this user control in a generic ASP.Net page, it doesn't prompt me for "pRequiredParam". Of course, if this was a "normal" class, I would have to supply "pRequiredParam" when I instantiate the object. Is this not possible with a User Control?
While you can certainly create a custom constructor like the one you show in your code sample, you cannot force the designer to make use of it. How would it determine what to send as argument to the constructor?
However, you can load the control dynamically in your code-behind file, and then use whatever parameters it defines. Note though that if you want the control to also work well with the graphical designer, I think that the control need to have a public constructor that takes no parameters (but I think you get that automatically in VB.NET?)

Resources