Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Persisting non-form Model data in ASP.NET MVC

I'm still relatively new to ASP.NET MVC 3, and I have a conceptual question for those of you with more experience here.

Lets say for (simple) example I have a signup form for an event. The form would show the name of the event, and a text box where the user could enter their name. The ViewModel would look something like this:

public class SignupFormViewModel {
   public string EventName { get; set; }
   [Required]
   public string VolunteerName { get; set; }
}

The Razor view might look something like this:

<h2>Sign up for @Model.EventName</h2>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<div class="editor-field">
    @Html.EditorFor( model => model.VolunteerName )
    @Html.ValidationMessageFor( model => model.VolunteerName  )
</div>
}

If the user submits the form back to the server and the ModelState is invalid, we return the original View and pass back the Model so we can display the errors. (we're assuming for this example that this is an error not handled on the client)

The trouble is that in my example view shown above, the EventName is not submitted with the form data. I only want to use it for page content, not a form field. But if I have to go back and display validation errors to the user, I've lost the EventName property.

So what are my options for preserving this non-form-field item through a post which comes back to the same view?

I know I can make a hidden field to hold the EventName property, but there's just something that doesn't smell right about being forced to put every non-form-field property into a hidden field. I also know that I could go into the HttpPost action in my controller, and reload that data back into the Model before returning the view, but that feels clunky as well.

I guess I have a good understanding of the basic ways to do this, but I was wondering if there was a better way or best practice that felt cleaner... or if I just have to learn to deal with it :-)

Thanks

like image 933
Ben Brandt Avatar asked Jun 04 '13 18:06

Ben Brandt


1 Answers

There is nothing wrong with using a hidden field for this. This is quite a conventional way of persisting things over a request when you don't actually want them to appear as form fields.

Bear in mind that HTTP is stateless, so dropping something on the page and picking it up again in the POST request is - in fact - a more conformant way of persisting that data over multiple requests than using another mechanism that gives the illusion of statefulness.

If you feel that this clutters up your markup too much, you could try putting the values into the TempData collection on the initial GET request, which will exist only for the duration of the next request, allowing you to pick it up in your next controller action:

TempData["MyVar"] = model.EventName

However, if you want this to be persisted in your model as is the conventional (and - in my opinion - best) way of doing this, hidden fields are still the way to go:

@Html.HiddenFor(m => m.EventName)

For further reading, you might also consider cookies or session state, though neither of these will persist the value in the model. Both of these mechanisms have their limitations, however, which I outline in another answer, here.

like image 200
Ant P Avatar answered Sep 22 '22 11:09

Ant P