Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you remove the HTML Field Prefix from strongly typed models in MVC 3?

I have a view model like this:

public class EditVM
{
  public Media.Domain.Entities.Movie Movie       { get; set; }
  public IEnumerable<Genre>          Genres      { get; set; }
}

Movie is the real entity I wish to edit. Genres is simply present to populate a drop down. I would prefer that when I call:

@Html.TextBoxFor(m => m.Movie.Title)

inside my strongly typed view that the input control have a name = "Title" instead of "Movie.Title"

I do not wish to split my view into partial views or lose my strongly typed view by using ViewData or the like.

Is there a way to express to the View that I do not wish to have the Movie. prefix? I noticed that you can set:

ViewData.TemplateInfo.HtmlFieldPrefix = "x";

in the controller, but unfortunately it seems only to allow adding an additional prefix. Setting it to "" does nothing.

Is there any work around for this? Or am I stuck with the unfortunate prefix that isn't really necessary in this case if I wish to keep strongly typed views and lambdas?

Thanks for any help.

Update:

Here's the controller actions to maybe make things a bit clearer.

public ActionResult Edit(int? id)
{
  var vm = new EditVM
  {
    Movie  = id.HasValue ? _movieSvc.Find(id.Value) : new Movie(),
    Genres = AppData.ListGenres()     
  };
  return View(vm);
}

[HttpPost]
public void Edit([Bind(Prefix = "Movie")]Movie m)
{
   _movieSvc.AddOrUpdateMovie(m); //Exceptions handled elsewhere
}
like image 747
C.J. Avatar asked Jan 26 '12 23:01

C.J.


People also ask

What is strongly typed model in MVC?

Strongly typed views are used for rendering specific types of model objects, instead of using the general ViewData structure. By specifying the type of data, you get access to IntelliSense for the model class.

What is strongly typed and loosely typed in MVC?

In ASP.NET MVC, we can pass the data from the controller action method to a view in many different ways like ViewBag, ViewData, TempData and strongly typed model object. If we pass the data to a View using ViewBag, TempData, or ViewData, then that view becomes a loosely typed view.

Which Razor syntax is used to strongly type a view to a model?

This is done using The @model directive, which is placed at the top of the view file specifying the type of the ViewModel that is being passed. When you use @model directive, the razor engine assigns that type to the Viewdata. Model property The Model property then returns the type declared.


2 Answers

No, in order to do what you want you would have to rewrite the Html helpers, and then you would have to write your own model binder. Seems like a lot of work for minimal gain.

The only choice is a Partial view in which you pass the Movie object as the model. However, this would require you to write your own model binder to have it be recognized.

The reason you have to do m.Movie.Title is so that the ID has the correct name, so the model binder can recognize it as a member of your model.

Based on your update:

Your options are:

  1. Use non-strongly typed helpers.
  2. Use a partial view.
  3. Rewrite the stronly typed helpers
  4. Don't use the helpers at all, and write the values to the HTML

Personally, i'd just use 1 or 2, probably 2.

EDIT:

Based on your update above. Change your code to this (note, Genres does not get posted back to the server, so m.Genres will just be null on postback):

[HttpPost] 
public void Edit(EditVM m) 
{ 
   _movieSvc.AddOrUpdateMovie(m.Movie); //Exceptions handled elsewhere 
} 

EDIT:

I did just think of an alternative to this. You could simply do this:

@{ var Movie = Model.Movie; }
@Html.TextBoxFor(m => Movie.Title)

However, if there was a validation error, you would have to recreate your EditVM.

like image 183
Erik Funkenbusch Avatar answered Oct 28 '22 15:10

Erik Funkenbusch


I have a view model like this

I think that you might have some misunderstanding about what a view model is. A view model shouldn't contain any reference to your domain models which is what those Movie and Genre classes seem to be. I mean creating a new class that you suffix with VM and in which you stuff all your domain models as properties is not really a view model. A view model is a class that is specifically designed to meet the requirements of your view.

A much more correct view model would looks like this:

public class EditVM
{
    public string MovieTitle { get; set; }
    public IEnumerable<GenreViewModel> Genres { get; set; }
}

and in your view you would have:

@Html.EditorFor(x => x.MovieTitle)
@Html.EditorFor(x => x.Genres)
like image 38
Darin Dimitrov Avatar answered Oct 28 '22 16:10

Darin Dimitrov