Reputation: 391
How would could I represent a key / value pair as an ASP.NET MVC model? My form data is not backed by a strongly typed model.
My first solution was to design my form using Razor and use some extension methods to get the FormElement values.
@model IEnumerable<FormElementKeyValues>
@Html.TextBox(Model.GenerateID("Email"), Model.GetFormElementValue("Email"))<br />
This works but it becomes messy when I want to process data from a POST. I have no model so I am forced to fall back to using a FormCollection which means I lose the benefit of strongly typed model and validation.
A second solution (I haven't tried this yet) would be to create my individual form models and decorate the properties with custom attributes that help me get access to the key / value pairs.
public SimpleFormModel {
[FormElement("Fullname")]
[Required(ErrorMessage = "Required")]
public string Fullname { get; set; }
[FormElement("Email")]
[Required(ErrorMessage = "Required")]
[DisplayName("E-mail")]
public string Email { get; set; }
}
public ComplexFormModel {
[FormElement("Firstname")]
[Required(ErrorMessage = "Required")]
public string Firstname { get; set; }
[FormElement("Surname")]
[Required(ErrorMessage = "Required")]
public string Surname { get; set; }
[FormElement("Email")]
[Required(ErrorMessage = "Required")]
[DisplayName("E-mail")]
public string Email { get; set; }
}
This would allow me to use a strongly-typed model within my view along with the standard Razor Html Helpers.
<div class="editor-field">
@(Html.TextBoxFor(model => model.Firstname))
@(Html.ValidationMessageFor(model => model.Firstname))
@(Html.DisplayFor(model => model.Firstname))
</div>
Upvotes: 1
Views: 3782
Reputation: 15334
I think you're way over complicating this task...
Models are there for you to both render, and consume from your Razor views...
So for instance, say I had a website selling tickets to festivals, and I have a order form I want to make reusable across all the different events I'm selling tickets for and that I wanted to pre populate the name of the event in that form... this is how you would do it...
First of all you need a model,
public class RegistrationViewModel {
[Display(Name = "Event")]
public string EventName { get; set; }
[Required]
[Display(Name = "First name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last name")]
public string LastName { get; set; }
}
Next let's imagine we have a Events
Controller with an Action called Register
public class Events : Controller
{
public ActionResult Register(int id)
{
Event event = DbSource.FindEventById(id);
RegistrationViewModel model = new RegistrationViewModel
{
EventName = event.Name
}
return this.View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register(RegistrationViewModel model)
{
if( ! ModelState.IsValid )
{
return this.View(model);
}
// ship the tickets, return thank you view, etc...
}
}
And finally our view....
@model RegistrationViewModel
@using (Html.BeginForm("Register", "Events")
{
<div>
@(Html.AntiForgeryToken())
@(Html.LabelFor(model => model.EventName))
@(Html.ValueFor(model => model.EventName))
@(Html.LabelFor(model => model.FirstName))
@(Html.TextBoxFor(model => model.FirstName))
@(Html.ValidationMessageFor(model => model.FirstName))
@(Html.LabelFor(model => model.LastName))
@(Html.TextBoxFor(model => model.LastName))
@(Html.ValidationMessageFor(model => model.LastName))
</div>
}
I've written this on the fly so I don't know if it will compile as is, but what I've shown you is basically all there is to it...
Upvotes: 1