I have a page with a form that accepts a list of account numbers into a text box, a bulk search essentially.
This does posts to the server, does a validation exercise and then if sucessful redirects to a display page.
Currently the list is added as a GET variable in the URL to the display page. This is limiting in that it means users can mess with it and larger data sets may be a problem. It also allows for a bypass of the validation but this is accounted for.
I see 2 general solutions which are basically variations of 1 theme:
Save the list to a DB and pass a key to load this to the diplay page.
Save to MemoryCache and again pass the key to the display page.
Based on these options it seems that 1. is better if I need multiple IIS node but needs manual cache cleanup where 2. will clean it's self up but may be a problem if I need to scale. This will be an intranet applcation so scale will probably not be required.
Is there a "industry standard" approach to this class of problem. I'm coming from the winforms world where keeping track of state wasn't an issue.
I don't think you really have to redirect to the display page at all. From the controller that gets the user input and prints the result just return the View that should render the results like:
public class SearchController : Controller
{
public ActionResult SearchForAccounts(string[] accounts)
{
var searchResults = db.Search(accounts);
return View('ResultsView', searchResults);
}
}
If you really really need to redirect, I guess you chould save the results into the application Cache and later if you need to scale you could use a Redis Cache provider for example, but again you should be able to show the required view.
Whether it's Webforms or MVC, I recommend not getting into the pattern of separating validation/processing and results into separate pages.
I'm guessing that if the data is invalid you want to put it back on the page so the user can edit it. (That's a guess inferred from what you're asking.)
You can post the data, and then if the data is valid then the "result" page shows the results. If the data isn't valid then the page can re-render the input form, populate it with the original inputs, and display a validation error. That way the user can modify their original input and try again. (Just be sure to escape/unescape if you're taking user input and reflecting it back onto the page.) That's easier if the form is a partial view (MVC) or a user control (Webforms.)
Related
I have a couple of pages for e.g. Product that look almost the same. I have Product/Add and Product/Modify/{id} pages where one is an empty form to add new Product and the second one comes already filled with data for a current product and can be updated with additional information. Because Razor Pages separates this into Add and Modify PageModels, I have a different cshtml view for each of them.
I tried to use ViewComponents to build reusable parts of these views, but they are only good if all you want to do is display data. Because ViewComponents don't support Binding all I have left is somehow send ajax requests and append the data to submit, which even sounds wrong and probably isn't the right approach.
Is there any other way of creating these pages without duplication?
You can create one page for create and edit by sending a new object of the Product model (with no data in id attribute) and a created object (with data in id attribute) in case of editing. And in the view you can do rendering based on the sent object (whether it is new or not).
Wanted to see if somebody can provide some suggestions/pointers on how to address this issue I am currently facing
.
Scenario is likeā¦
I have a Page say A where search is performed and data is displayed.
On Page A there is an ActionLink which passes an ID of the selected record to the page B.
Before redirecting to page B, I need to store/preserve form data of Page A (I do not want to use session or hidden filed as data is critical).
Once user is done working on Page B, I need to save changes on Page B and redirect back to Page A.
Here Page A should make a Post request based on preserver form data in step 3. Purpose is to display back searched data that was there before redirecting to Page B.
Something like..
View A
// Search textboxes here
// Search data list here with ActionLink column
View B
// more controls here
// Submit button - saves changes on this page.
// after submit button processing need to go back to View A
// and display the same Search data List based on Seach textboxes values
// those were entered by user before coming to this View B.
// Ques: Not sure how to persist data from View A between calls to View B and then View B to View A.
Does anybody has any better approach to achieve this?
For now the solution I have is...
Make an ajax POST request on ActionLink click and save the
formcollection in cache using controller.
Make default ActionLink GET request passing ID and in controller
return View B.
On View B, on submit do ajax POST request to save data on Page B and
return data from cache in ajax success function.
Make another ajax POST request using data retruned in above ajax
success to display View A.
Thanks in advance
If you're relying on full page refreshes then you need to use Session. You didn't give a reason as to why you don't want to use it, but Cache object is totally inappropriate for this purpose as it can be cleared out if the server needs to regain some memory, as well it is shared between users. Session is specifically built for the purpose you're describing - preserving data between full page refreshes.
Alternatively I would look into building your site as a Single Page Application, aka, you don't do full page refreshes between navigation, and can store data in a javascript object on the client. Due to the fact you put a lot of emphasis that the data is critical, the Session might be safer though as your javascript objects will get cleared out if the user accidentally navigates away from the page, where is a server based session object will preserve it for the duration of the session lifecycle.
You can also store the data in a cookie/local storage object (html5), but this is probably overkill for what you're doing.
I'm new to ASP.NET. I'm designing a user interface in Asp.NET and C# where the user can login and then launch an application. When using this application the user has to fill out a form that is 10 pages long.
So, I have used navigation menu and designed the interface in such a way where every page is different menu item and it is a static menu. The user fills out the details on the first page of the form and saves it and the data gets saved in the database.
The problem is he moves to the other page by clicking the menu tab; when he comes back to the first page by using the menu tab for that page all the filled in data is gone and he sees a blank page. I know that is how it works but I want it in such a way that in one sitting when he is filling out the data on the second page (after filling the data on first page) on reverting back to the first page he should be able to see the data that he had filled out.
What concept can I use? I'm not sure view state will be helpful in this scenario.
You should look into using the Session State variable for storing his information over the entire session. If the user is logged in you should think about storing his information that he enters in a database and having a Boolean state of "ApplicationFinished" to check if he has finished it or not. Otherwise I would have a call on each page to retrieve information from the database that has already been added, so that he can fill out information at different sittings or all at once.
http://msdn.microsoft.com/en-us/library/ms178581.aspx
Session State may be too long term for you, and if that is the case do some research on ViewState. There are a lot of different ways to tackle a problem like this. It all depends on which technology will fit your needs the best.
http://msdn.microsoft.com/en-us/library/ms972976.aspx
Also, if you're using a tab system think about using the AJAX tabs so that the data will remain on the forms even while tabbing through the different tabs.
http://www.dynamicdrive.com/dynamicindex17/ajaxtabscontent/
Well, if you are write the data on database, i guess the best (fast) workaround is to add a column named "completed" to the table the hold this informations. If the flag "completed" is not setted to 1, you load the database information and fills the page controls.
When you create a new record in the database, get the ID of the record and set it on Session. If the user gets back to the first page (previous page), you can recover the information ID and load the data.
As long as you are learning new things... add jquery to the list and leverage the JQuery Wizard Plug In. It will allow you to integrate your "10 page form" into a single unit, which can then be sub divided, routed and managed more easily. You can leverage AJAX to save each step, while offering built in navigation and validation methods.
I would suggest that you switch to using client-side javascript to control your tabs. That way your form data stays in the fields when you switch back and forth between tabs. You can use javascript buttons to guide the user from tab to tab.
I've done this using JQuery. I actually had 150 fields that needed to be captured (they were all required). I group like data on different tabs and then had buttons ('< Previous', 'Next >') which would activate different tabs.
When they are done, then display the 'Save' button.
This not be what you are looking for, but if your problem is that you want all of the input of a previously filled page to show up when a user navigates back to it, and you have already saved all that information, then you can try something like this:
HTML
<input type="text" id="yourID" name = "yourName" value = "<%=data%>"/>
Then all you need to do is set data to public in the code behind. Then to get the value for data just make a call to your database.
Make sure that you make data empty on the init call public string data = ""; or whatever type it is. This way if there is no info, then it will be blank, and if there is saved info, then it will be filled in.
You can also attempt to pass all the data through params in the url like so:
C#
Response.Redirect("webpage.aspx?data=" + data + "&data1=" + data1);
Or though javascript:
window.location = ("webpage.aspx?data=" + data + "&data1=" + data1);
To get the request do this:
if (Request.Params.AllKeys.Contains("data"))
{
data = Request.Params["data"];
}
This way is less ideal though if there is a lot of data being passed.
usually I would setup a GET POST Redirect cycle, however I have run into a situation where rather than redirecting, I need to just return a new view. The problem with this is that the new page has the URL of the previous page (because I haven't redirected, i've just returned a new view). Is there any way of changing the url of page presented to the user without redirecting?
I am actually implementing a wizard where I need to persist data between pages, however I have no way to persist data through a redirect (TempData is disabled..) which led to the above approach. A possible solution is to create a table to store the temporary data that I need to persist but this is undesirable. I also don't want to end up with one view with every field for the wizard and just use jscript to hide show the different steps.
Any help, tips or general advice would be really appreciated.
Thank you.
No, you would have to redirect to change the URL effectively.
You can always POST to a new URL, right?
In your wizard, you could do
myWizard/step1
myWizars/step2
etc
There's no problem with that, except that they'll repost if they hit F5.
Between the the posts, you can model bind and then print out html hiddens.
ViewState 2.0
You can make your View a strongly-type view so that you can pass your data to that view when you return it. Just make a view-model out of the data you want to persist.
return View("MyViewPage", objData);
Perhaps you could do something like this?
Wrap the view with your form up in a partial.
Have it post to the second URL.
Perform validation and return the same partial if it fails.
Otherwise, return your second view.
You'll have to make your form a child action in order to stop the PartialViewResult from being the entire rendered markup on the POST, though (and post to the parent action), so this does have some limitations in terms of what you'll be able to render (e.g. you might have some issues to work around if you want your layout to change for the second page).
This way you can keep your ModelState intact for your validation errors, return your second view directly from the POST and still have a different URL.
This may be a basic question... However I've just been picking a solution without giving much though to it...
Consider a page with a grid of forms: /FormList.aspx
where choosing to edit a form redirects the user to a page like: /FormEdit.aspx?Id=2
I usually am okay with passing the values in the query string, because I check in the code-behind of FormEdit that the Id is valid. Which is the best way to pass the value, though: session or query string? Or other?
While the user is editing the form... I usually save the Id temporarily in session (to avoid getting it from the url again). During the user's form edition, what is the best way to store the value? In the session or in a hidden field ? Or other? (When I want to store a temporary DataTable, I believe I can only use the session, but when it's an integer value...)
Thanks in advance for your suggestions :)
I would suggest not to use Session for something that can easily and quickly be stored and checked in a query string or hidden form field; the information you seem to be talking about here is perfect for the query string.
Note that Session could introduce bugs when someone attempts to edit multiple forms at once in different tabs. When they save one, the Session value taken would be from the last one they loaded up to save... likely not what you will want, and it would likely be difficult to figure this out.
What you should do is persist the formID in the query string/form fields, and just double-check it for sanity when they submit the save; Make sure it's an ID that exists and that they are allowed to edit, for example.
Normally QueryString is a good choice if you are having very small data to trasfer between your pages.
2- Session would be a great when you want to store user specific data.
in you case , best would be the querystring as you are sending very small data (ID ) to the next page.
A few things to consider:
If manipulation of the value is a security risk you need to either save it on the server side, or secure the value client side(Which isn't easy to get correct). Or even better: recalulate them.
Saving in the session can easily create problems if the user has the website open in several tabs at the same time. It can also break the back button.
For example if you safe the ID of the item the user is currently editing in the session, and the user edits two entries at the same time the content of the one he started editing first might be written into the entry he started editing later.
My suggestion is to keep the value in a session variable, but when you run the page_load of FormEdit.aspx for first time, save the value in the ViewState of the page, and clear the session var.
Something like that (in page_load of FormEdit.aspx):
if (!IsPostBack)
{
ViewState["MyVar"] = Session["MyVar"];
Session.Remove("MyVar");
}
The problem with ASP.NET and query strings is that they persist on postbacks. That is, the form action for any page defaults to the url including the query string that was used to load it.
If the ID in question is just used to choose a particular form (and is not related to user data) this is not a big deal, in fact it's probably what you want.
On the other hand, if it identifies a record, you may not want this. Assuming you code things properly, this should not present a security risk, but it can give the user the impression that there is one by exposing the internal ID of a record in the query string. It also just looks unfortunate.
There are ways to work around this, and I think in 3.5 you can programatically change the form action. (It used to be you had to use javascript to do that - even though the form action was exposed it could not be changed).
The best way to deal with this is avoid query strings for any data record identifiers. Use POSTs to load data records instead, e.g. instead of using an asp:HyperLink control, use an asp:LinkButton control.
Of course, since POSTS load the same page they are sourced from, this requires that your forms be on the same page as your list. So, instead of having two separate pages, FormList.aspx and FormEdit.aspx, just put the code on the same page so you can post back directly. Presumably each of your forms is in a UserControl anyway. So your main page just has the job of choosing which usercontrol to show, everything else is delegated to the user controls, and all the parameter-passing can be done through posts inside your main page. This is a better architecture and keeps everything nice and clean.