How can I preserve the url (with the querystring) after an Http Post but also add an error to the Model State?

Multi tool use
How can I preserve the url (with the querystring) after an Http Post but also add an error to the Model State?
Essentially want I'm trying to do is authenticate a user by having them enter their account and their social security number. If they enter an incorrect combination, I do the following on the Authenticate
post action:
Authenticate
ModelState.AddModelError("Authenticated", authenticationError);
return View();
This displays the error, but then I lose what was in my query string. An alternative to keep the query string is:
ModelState.AddModelError("Authenticated", authenticationError);
return Redirect(Request.Url + "?returnUrl=" + returnUrl);
This will keep the query string, but the error will not display. I assume this is because the ModelState
has changed.
ModelState
I need the returnUrl
because the user is forced to the Authenticate
page whenever they click to view a specific event. I want to set it up so that they still go to this event once they authenticate themselves.
returnUrl
Authenticate
Is there a way I can achieve both the preservation of the query string and display the model error?
2 Answers
2
Your second scenario doesn't have the model state because when you do a redirection the browser makes a separate request to that location, separate requests = new model state.
I would suggest using your first scenario and place a "ReturnUrl" in your model and render it to the client as a hidden field.
//In your model add the ReturnUrl Property
public class AuthenticatModel
{
public string Account {get; set;}
public string SocialSecurityNumber {get;set;}
public string ReturnUrl {get;set;}
}
ModelState.AddModelError("Authenticated", authenticationError);
//Set the return URL property before returning the view
model.ReturnUrl = returnUrl;
return View(model);
@* add the return URL as a hidden field to your view so it can be posted back *@
@Html.HiddenFor(model => model.ReturnUrl)
On the contrary, putting it in the model makes it more clean, because looking at the model will show you what is needed to be on the view. The viewbag obscures your implementation.
– Jay
May 31 '13 at 15:21
Thank you! This works great! If I were to go the
ViewBag
approach, how would I keep from losing the returnUrl
if the user isn't authenticated properly? From what I've seen, returnUrl
will become null
if a user doesn't authenticate properly on their first attempt. Am I missing something with this?– The Vanilla Thrilla
May 31 '13 at 16:36
ViewBag
returnUrl
returnUrl
null
If you choose to use
ViewBag
you'll have to write out the hidden field in the form area of your view, then on the next request in your controller method interrogate the Request
object for the form field "ReturnUrl".– Jay
May 31 '13 at 19:57
ViewBag
Request
Ivan Korytin's answer was the best (and only answer I could find which seemed to actually work properly without using hidden field hacks) which I've improved a little with Request.QueryString
.
Request.QueryString
You have to put the parameters as part of the form action:
<form action="@Url.Action("CreateEntity", "Employee")?@(Request.QueryString)"
enctype="multipart/form-data" method="POST">
When you perform the following the query string (and GET
parameters) are now preserved:
GET
[HttpPost]
public ActionResult MyAction(MyAction model)
{
if (!ModelState.IsValid)
{
return View(model);
}
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Or just pass in the return url using the ViewBag to avoid polluting your pretty model.
– mcNux
May 31 '13 at 15:17