0

So previously this view was bound to only one model but now I am using:

@model Tuple<Namespace.Models.Model1, Namespace.Models.Model2>

So now when I bind:

@Html.HiddenFor(p => p.Id);

The compiler does not know which model to use and as a result throws this error:

The type arguments for method 'InputExtensions.HiddenFor<TModel, TProperty>(HtmlHelper<TModel>, Expression<Func<TModel, TProperty>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.  

I tried to explicitly infer the model using:

 @Html.HiddenFor(Model1 => Model1.Id);

But I get:

The type arguments for method 'InputExtensions.HiddenFor<TModel, TProperty>(HtmlHelper<TModel>, Expression<Func<TModel, TProperty>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.  

So I try the below:

 @Html.HiddenFor<TModel, TProperty>(HtmlHelper<TModel> p => p.Id);

The Id property is defined in Model1.

And get a whole bunch of other errors. After extensive reading online, I still have not found a solution. How do I get around this?

Harold_Finch
  • 682
  • 2
  • 12
  • 33
  • Do not use a `Tuple` for generating form controls - you cannot bind when you submit - a `Tuple` has no parameterless constructor. Use a view model. –  May 12 '17 at 11:41
  • @Stephen Muecke example? – Harold_Finch May 12 '17 at 11:53
  • [What is ViewModel in MVC?](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc). Create a view model containing the properties from `Model1` and `Model2` that you want to display/edit in the view. –  May 12 '17 at 11:54

1 Answers1

2

As @Stephen Muecke mentioned, the way to accomplish mixing your models into one view is to create a ViewModel:

public class Model1
{
    public string Model1Prop { get; set; }
    public string Model1Name { get; set; }
}
public class Model2
{
    public string Model2Prop { get; set; }
    public string Model2Name { get; set; }
}

Those are your Domain Models, now suppose you want to register those properties in the same View:

public class RegisterViewModel
{
    [Required]
    public string Model1Prop { get; set; }
    [Required]
    public string Model2Prop { get; set; }
    [Required]
    public string Model1Name { get; set; }
    [Required]
    public string Model2Name { get; set; }
}

Since those are the fields that will be displayed on the view, this is where you put DataAnnotations for your model validation. You'll get whatever the user types on these inputs in the controller action, then just pass whatever you need to your Domain Models. I remember struggling with this question myself not so long ago, hope it helps.

James Braz
  • 81
  • 5
  • So now, in the event that your are using Entity Framework, won't the View Model break Code First and require me to drop and recreate the database to cater for the newly added/modified properties? – Harold_Finch May 15 '17 at 09:53
  • I'm really not experienced with EF, but you'll have problems with Code First approach because of the Data Annotations being on the ViewModel instead of the Model. I did some research on this and found this answer: http://stackoverflow.com/questions/37278517/update-entity-with-viewmodel-and-entity-framework-6 – James Braz May 15 '17 at 13:47