.net MVC Get Post Return View - c#

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.

Related

Keeping data across a redirect

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.)

Passing data between Views and Controller

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.

When do you use Html.Action over Html.Partial

I still don't get the primary purpose of Html.Action in asp.net mvc. I have been using Html.Partial every time I need to load up a partial view or wanted to split up some code in a view to clean it up.
Where does Html.Action fit into all of this (e.g. where would you want to use Html.Action and not use Html.Partial)?
Edit
The answers seem to be use Html.Action for dynamic data. I don't get this as you can use Partial Views for Dynamic data as well.
For instance if a user on my site edits a row. A ajax call is made to a method and I go grab that row from the db. I then return a parital view of a form that has all the data on it ready for editing. If an error occurs then I return a json result with the error method and my javascript consumes it and alerts the user.
If all is good then the rendered html is put into a jquery dialog and displayed to the user.
Is it because you can use the "ChildActionOnlyAttribute" that makes people use Action instead?
Ankur has the right idea but I find you can really simplify the concept down further.
For me it comes down to What versus How
If you know what you want to render but not how it's likely you'll use a partial to let it determine how to render the information.
For example, maybe your view model is for an invoice. Your invoice view model probably already has all the information you need about the invoice itself, including an enumerable of the line items on the invoice perhaps. A partial might be a good choice for the line items so that it's self contained. You already have the line items details (the what), but a partial will handle how it gets rendered (the how)
On the flip side, maybe your invoice view model has a customer ID on it but no actual customer details. Here you don't have the what, so you'd pass in the customer ID to an Action and it'll get what data it needs and pass it off to the view to render how it seems fit.
So in summary if you already have all the data you want to work with, just stick with a Partial, but if you are missing information that you need to obtain, Action would be better.
Where this get really fuzzy around the edges is when a Partial view includes the ability to retrieve it's own data via Ajax (or other technologies). In which case you might be able to get away with making that Customer details portion in my example, a Partial, and have it retrieve the data it needs Using Ajax after the client get's the response. But that's more up to you if that sort of thing even makes sense for your implementation.
Addendum:
It's worth noting that if you decide to try out ASP.NET MVC Core, ChildActions are no longer available. In which case your choices will be limited to partial views, ajax, or the newly introduced feature of Components. The last of which is similar to ChildActions, but slightly different in how they are implemented.
Perhaps an example will make this clearer.
Let's say you have a menu which appears on every page, so you put it in your layout. The menu will never change - there is just some basic navigation links, Home, About, Contact us etc, so you just use a normal partial view. This will work fine - as the content is static - you don't need to go to a database to get the data. You can just use #Html.Partial("Menu");.
Later you decide you need to change the menu so that it gets all the links from a database. You update your partial view to have a model that is a List<string> - one for each link.
Now, if you still want to just use a Partial View, every action would need to query the database to get the list of links, and every Model for every View would need to have a List<string> property for the links, so that it could pass this to the Menu Partial View. This would be a bad idea.
Instead, you would make a new Child Action GetMenuLinks() - this would query the database to get the links as a List<string>, and pass this to the Partial View. This puts the Child Action in charge of getting it's own data. This means you only need to have this query in one place, the 'About Us' action for example doesn't need to worry about getting the list of links for the menu.
Partial views
Use for sharing subsections of view markup between views. Partial views can
contain inline code, HTML helper methods, and references to other partial
views. Partial views do not invoke an action method, so they cannot be used
to perform business logic.
Child actions
Use for creating reusable UI controls or widgets that need to contain business
logic. When you use a child action, it invokes an action method, renders a
view, and injects the result into the response stream.
I use Html.Action() to load dynaimc content that I do not wish to contain in the view model (for instance, user information in a sidebar). It is very useful for keeping input and output view models identical.
Note that I always use Html.Action() in conjunction with applying the ChildActionOnlyAttribute to the controller method that I am calling so that the HTML fragment is not accessible via the URL.
Use Html.Partial when you require a subset of your view model to render the section in question--usually it is something that has to do with what you're working on. If could be a subsection of a form, a relevant content piece related to the main view etc. A partial receives its model information from the parent view.
Otherwise use Html.Action to render content that is independent of your main view, such as a navigation piece, an aside, or other distractions. Html.Action uses its own model provided by its controller, rather than provided by the parent view.
This question is answered (and elected for 149 times!) here:
Html.Partial vs Html.RenderPartial & Html.Action vs Html.RenderAction
Update
Sorry, meant to send you these postings rather
MVC Html.Partial or Html.Action\
#Html.Partial() Vs #Html.Action() - MVC Razor
Hope this helps.

Filtering Pane, ASP MVC 3

My plan is to create a a two-pane page using ASP MVC 3. The left pane should be a small filter pane and the right the main content, showing a list of objects (say products).
Initially all products will be shown since no filter is applied. When selecting "only red", only red products are shown in the list. When further selecting a price range, only products in that price range will be shown.
Functionally the plan is to implement the filtering pane as a treeview with checkboxes (to be able to drill down to more and more specific filtering options), graphically it will probably be enhanced in some way to improve usability.
What is the best way to implement the coupling between the filter pane and the main list? Everything should work server side, but should of course use javascript (jQuery) when possible for direct feedback.
The simplest way is probably to make it closely coupled solution, calling a specific Asp MVC action using a custom-built javascript (with fallback to a form post). Doable enough, sure, but how to make the solution reusable? Also it would be nice to not loose all filtering data when navigating forward and back, i suppose GET arguments is the only decent way to do that?
Are there any best practices, any guidelines or anything to base this on to make a nice modular structure for filtering.
Victor, I recently had to solved this same problem. I'm not promising it's the best way but it's pretty clear and should even work well in case JavaScript is disabled (who even does that anymore?).
Create a that calls the action with all the field-selectable search options like "only red".
To that same form, add empty, hidden value for the things not directly as fields (paging, sorting...)
Setup your form with the excellent and very easy to use JQuery.Forms (http://www.malsup.com/jquery/form/) to make you form submit via JQuery (all your form values will be passed as JSON on form submit).
Make your back/next/paging/sorting links pass their individual values via query (no-JS fallback) and use JQuery to capture their click events. The JQuery click events on those links should assign the value of the value passed by the link (page number, sort column name...) to the corresponding hidden field in the form and call submit (with thanks to Jquery.Forms will submit via AJAX).
When you configure JQuery.Forms, you can define a callback method. In the callback method take the result (the HTML returned by your action that should contained your filtered+sorted+paged result) and replace the document (or DIV if you used a partial action + view) with that.
The result is a JQuery solution that works when JS is off. You also have very minimal JS code to write other than wiring the event handlers.
I'm not sure if it will be helpful but in MVC 3 you have access to a property called IsAjax from the view so you can do specific things to server a slightly different view when called from AJAX.
Cheers

Ideas - storing jquery parameters for later use in partial view

Ok, let me try to clearly explain what I'm attempting to accomplish here.
Basically, I have a site that is using a liberal dose of jquery to retrieve partialviews into a consolidated 'single view'. So far so good - it all works great and is very performant.
However, I would like to have the ability to 'flag' (using a button) any such set and as a consequence of flagging it, add it to a functional area that I have dubbed 'active-tasks'. What I'd like to do is to be able to then goto that 'active-tasks' panel and see a range of ui tabs that represented the consolidated views that I had added. Clicking on any tab would then re-invoke that consolodated view afresh with the parameters that had been used at the time of flagging it. This would therefore mean that I'd have to store the parameters (?) for creating that consolidated view, rather than the generated html (this part i can do at the moment).
So, any thoughts on how to elegantly store the code required to generate the consolidated view on clicking a tab button - no pressure :)
cheers - jim
Actually, after a minimal amount of research, it looks like the newly updated .data() jquery method (with the ability to add an object to the payload) may work for the above.
http://api.jquery.com/data/
basically, this allows you to add hash type keyed data to an id element for use later, so in my scenario above i could simply attach the parameters required to invoke the action method that related to my consolidated view on the tab.
I'll let you know how i progress with this...
jim

Categories