I'm presently in the process of reworking a MultiViewControl based wizard process for our web application. I am having an rough time trying to make sense of the order that events are happening (Page_Load, Init, prerender, etc). Does anyone out there on the interwebs have details on dealing with one of these controls? Please don't just say 'google' it. I've done that and have yet to find a good, comprehensive site yet.
Admittedly, I haven't really elaborated on the problems I'm having with this control, so I'll try to do that:
Primary problem is the initialization of UserControls that live in different Views. In the existing codebase, the programmer was using a combination of multiviewcontrol.ActiveViewIndex = WHATEVER and Response.Redirect("PageWithMultiView.aspx?nextstep") and it made it all very convoluted. My task is to attempt to remove the Response.Redirect calls and use only the setting of the ActiveViewIndex. Is this even possible? Also, there are some cases where I need to initialize a control in a particular view only on the initial load and not on subsequent postbacks. I can use something like the IsPostBack flag but this is only ever set to false on the initial load. Subsequent reloads IsPostBack == true. I basically want to have IsPostBack set to false for the initial load of each View. Can this be done without doing a Response.Redirect to itself?
Hopefully this will make some sense to someone out there.
Thanks.
Greg.
I am having an rough time trying to
make sense of the order that events
are happening (Page_Load, Init,
prerender, etc).
Here you have all details about ASP.NET page lifecycle and events: http://msdn.microsoft.com/en-us/library/ms178472.aspx .
In terms of MultiView - you should NEVER use Response.Redirect when you work with MultiView.
If user can not switch to previous view then you can check previous ActiveViewIndex value before setting it to the new value, e.g.
if (mv.ActiveViewIndex != newIndex)
{
// this view is displayed for the first time
}
If user can switch to the previous views, I suggest to place an information about already used views in session or by placing hidden field on the form with ids of the views that have already been displayed and to use that information instead of IsPostBack.
Related
I have a single-page site that has an UpdatePanel. Within that UpdatePanel, there are UserControls that are dynamically loaded.
All linking between 'pages' (which are just UserControls) is done by using a WebMethod that changes a Session variable that stores the UserControl to load. The page reloads, with a new UserControl, and everything works great!
The downside to this methodology, however, is that I'm aware that Session variables don't scale well. Too many of them kicking around is not a good thing, so I've heard. I've unsuccessfully attempted to use different methods but not have been able to succeed. I'm looking to set the UserControl to load very early in the Page Lifecycle.
I've tried HttpContext.Current.Items, UserControl public properties and even UserControl HTML injection. It's just a big mess.
Is there a best practice for this type of scenario? Any helpful links or suggestions?
All is much appreciated.
Clarity update
I'm looking to change the UserControl to be loaded by the C# code-behind file through either jQuery method calls or a Webmethod. Session variables work, but don't scale.
I would use localStorage, you can store lots of information like this
localStorage.setItem('var', 'data');
and get the data back like this
var data = localStorage.getItem('var');
I have an ASP.Net form (Page1) where the user enters some data and then clicks the submit button.
As part of Page1, I have some Validators, including a CustomValidator which needs to do its validation back on the server.
When the user clicks the submit button a post is done to Page1 and the validation routine is run on the server and as long as I check Page.IsValid in the button click routine the form knows whether things have passed or not.
When the validation doesn't pass everything properly goes back to Form1 and the error message is displayed.
When the form does pass validation, I want to pass the data that the user entered to a second form (Page2) so that Page2 can be rendered correctly based on the data the user entered on Page1.
Is there a generally accepted way, or best way, to pass the data to Page2? Here are some ways I know about:
Call Page2 with a query string: This won't work as I need the data to not be visible to the user in certain cases.
Use the PostBackUrl on the submit button to go to Page2: As far as I know, this won't work correctly because then the server side validation routines for Page1 won't be run.
Use Session Variables: I don't know of a particular reason why this would be bad.
Use Server.Transfer: I don't really have any experience with this.
I would think that this would be a pretty standard thing to do but I'm having a hard time finding any information on the correct way to do it.
If you don't have a form of secondary storage for this data, using either Session storage or Server.Transfer would work.
You might find Server.Transfer is a little neater as, this way, you'll retain your POST values across the transfer. This will potentially save you a lot of cumbersome code playing around with session state, which, depending on how complex your forms are, could open the way to all kinds of unusual behaviour that you'd have to predict and plan to deal with in advance such as what happens when a user clicks the "back" button or - if you're posting across multiple pages - what happens when a session expires (plus Servy's examples of having multiple tabs open on the same page(s), all sharing the same session). Working with session state can be messy.
Perform your validation on PostBack then, if Page.IsValid, do:
Server.Transfer("/FormPage2.aspx");
Server.Transfer preserves Request.QueryString and Request.Form, so you can pick up your POST values on FormPage2 and do whatever you need with them here - whether it be using them for conditional logic or rendering them out again as hidden fields to join them up with the values from the second page of the form (bear in mind that if you're doing this you'll have to revalidate the hidden inputs at this stage).
http://msdn.microsoft.com/en-us/library/y4k58xk7.aspx
I have used session state for handling complex forms in the past and found myself wishing I'd used Server.Transfer, which I plan to use for all similar endeavours in the future, unless I have a very good reason not to.
You might also consider using a multiview, but in my experience these can be very messy.
Hope this helps.
I think that the easiest solution would be to specify a PreviousPageType directive. It specifies a type that the page should expect to receive and you would do a normal POST to that page.
On the second page of your application, use the following directive:
<%# PreviousPageType VirtualPath="~/FirstPage.aspx" %>
You will be able to access the properties exposed and check for validity by using something like this:
if (PreviousPage != null && PreviousPage.IsValid)
Using the Session object is a standard way to pass information across forms.
#Servy gives a good explaination (in the comments below) on how Server.Transfer can help you in this case.
The other options you stated all have problems, just like you mentioned...
If you want to use Session:
In the postback of Page1 you can set the values:
Session["myVar"] = <Data you want to pass to page2>
In page2 in the OnLoad:
if (Session["myVar"] != null)
{
myVar = Session["MyVar"]
}
You can achieve this with Server.Transfer by adding a property to your page1. In your second page in page_load for example:
Page1 prev = Page.PreviousPage as Page1;
if (prev != null)
{
// access your property here and set up the page
}
Server.Transfer can safely receive a query string without fear of the user seeing it.
Instead of Session use Context.Items.
Context.Items["validationProblems"] = "...";
Server.Transfer("FixProblems.aspx");
My other comment is that in my experience it's more "standard" to keep the validation UI contained in the same form that's collecting the information. This enables "real time" feedback. In practice I think it's better to give a user information that their doing something wrong as early as possible.
Note, that's just in my experience though.. it's a big world.
It may be more that you presently require, but one alternative is to save the data in a database:
http://msdn.microsoft.com/en-us/library/6tc47t75%28v=VS.100%29.aspx
http://www.asp.net/web-forms/videos/how-do-i/how-do-i-set-up-the-sql-membership-provider
I understand that this will causes a page reload (partial or full, depending on how your UpdatePanels are set up)
But,
where in the code I should put it (client or server side)?
which control should I send to the method? Is it must be inside the UpdatePanel?
does this method work only for controls inside update panels?
must the control have a postback capability?
what is the engine behind this? How does this method work, so I could use it properly.
Thanks.
The function call returns a string of executable JavaScript, which you need to write to the client somewhere in your response.
Typically, you're sending your Page (this/Me) unless you have a control that you specifically want to handle the postback (ie, that implements IPostBackEventHandler)
GetPostBackEventReference is not related to UpdatePanels; if you have one, it will handle the postback.
No (see #2)
This makes a postback to the page. If you want it to raise an event when it posts back, you need to implement IPostBackEventHandler, either on your page or on one of your controls.
http://msdn.microsoft.com/en-us/library/ms153112.aspx
In my asp .net C# project I have a page defualt.aspx on which I have placed 2 components.
So in all I have:
1) default.aspx (main page, not doing much code in it)
2) wuc_Lookup.ascx (doing a lot here, grabbing data, setting session, etc)
3) wuc_PageMessages.ascx (has a couple of panels and labels for message output
)
The intent is to use 3) in any page in my application. 1) and 2) are already working. My issue is that the Page_Load sequence is:
1st default Loads
2nd wuc_pageMessage loads
3rd wuc_lookup loads
The problem with this is that The wuc_pageMessage is relevant only after wuc_lookup runs.
My intent was not to put code in Page_Load for the message wuc_pageMessage control because I wanted to be able to call a method to post the message during the component load of wuc_lookup. I do this because only after wuc_lookup do I set the session which I use for the message value.
I actually got values showing up if I put the code in wuc_lookup to manipulate the code-in-front server control (panels and labels) using this.parent.findControl syntax...
But then when I try to rip that code and put it into the code-behind for wuc_pageMessage, and then call the method from the wuc_lookup it has fallen out of scope or context...
So I tried to change this.Parent by passing httpContext.current.handler as casting it as page...that didn't work...then I tried passing Object sender from the calling component...that didn't work either. Neither of them had the Parent property and or it was null which led me to believe that once the wuc_PageMessages.ascx loaded it was a dead deal until a repost happens and that is ugly and something I don't want to do.
I am having some implementation issues and I am not sure what to do. I have been stunk on this for eight hours and Is there just something I am not seeing?
I want to keep away from spagetti code. I don't want to have to scatter code-behind in 3 different files. Theoretically I should only need 2 of these to talk to eachother. i don't want code-behind in default..it's basically just a container. I want to trigger the wuc_pageMessage from wuc_Lookup.ascx without having it be "in" wuc_Lookup.ascx (peer web user controls) I want that to always be a peer relationship. Any advice would be great ...thanks...
Try moving the wuc_PageMessages logic from the page_load to the page_prerender event.
If you are going to use the preRender you would do it on the default.aspx preRender because this event fires after the wuc_lookup. Prerender will not fire on the components for some reason. So yes, this only solves part of the issue. I am not sure how you would get the alreeady loaded component of wuc_PageMessages to get back into scope. If you try to reference components on a component that has already loaded, you will get a null, like they are not there or not in scope anymore... anyone have any ideas?
I'm a super beginner ASP.NET developer. I read that on every submit the request parameters are being populated to the controls and instead of reading the "Response.Form[]" parameters I can read the input parameters from the control itself.
Are there any events that I can catch all the submits before and after the magic happens?
Which method on the server side is activated that perform this magic?
Can I override it (for fun)?
Thanks,
Ronny
I believe that you are talking about the function of Viewstate and how control values are persisted.
This is a diagram that will show you the page load order for ASP.NET
For you, if you want to look before viewstate is loaded, you can work inside the Page_Init method.
see few tutorials
http://aspalliance.com/quickstart/aspplus/
http://quickstart.developerfusion.co.uk/QuickStart/
In asp.net all event, result in post-back. So, you can handle them in Page_Load, but it's classic way. For fun you can try it.
ASP.NET maps HTML input field values from the Request.Form collection to server control properties, such as TextBox.Text between the Page.InitComplete and Page.PreLoad events, as detailed in the ever-linkable ASP.NET Page Life Cycle Overview.
The actual mapping takes place in the non-virtual private method Page.ProcessPostData, so there's no real hook for modifying that process. (You can see this by downloading Reflector and reviewing the Page.ProcessRequestMain method.)
If you want to perform custom processing before or after the mapping, you can add a handlers to the appropriate events or override the associated virtual methods (Page.OnInitComplete and Page.OnPreLoad).