3

Now, I can show and update a model if I know its name and value. For example, here is my Student model:

public class Student
{
    public string Name { get; set; }
    public bool Sex { get; set; }
    public bool Address { get; set; }
}

And, here is what I have in my View:

@Html.TextBoxFor(model => model.Name)
@Html.TextBoxFor(model => model.Sex)
@Html.TextBoxFor(model => model.Address)

I want to show and update a model, but I do not know how many attributes it has and what their names and values are. For example, if I return a Fruit model to the view, I will need to show and update its attributes like Price or Weight. If I return a Student model, I'll need to show and update attributes like Name, Sex, and Address. I have more than ten models in my project. My boss says that I can use key and value like Dictionary<string,string> this way, and iterate through the model attributes, but I do not know how to do it.

ataravati
  • 8,891
  • 9
  • 57
  • 89
flower
  • 2,212
  • 3
  • 29
  • 44
  • Let me try to understand your questions. Are you basically trying to send 2 models to the view so you can update either or? – Moe Bataineh Aug 29 '13 at 16:58
  • So to clarify: You want 1 view that can handle editing multiple models? Normally you'd create 10 views, one for each model. However, you could achieve what you are trying to do by looping through the properties of the Model via Reflection and writing out different controls based on the type (bool = checkbox, string = textbox, etc). You could also create an encompassing model which calls a method to determine which fields to support, and how to display them. What you are attempting to do is fairly complex and might be overkill to avoid writing 10 distinct views. – Adam Aug 29 '13 at 16:59
  • http://www.gregshackles.com/2010/09/anonymous-view-models-in-asp-net-mvc-using-dynamics/ – Robert Harvey Aug 29 '13 at 17:07
  • Use a dynamic model type. – Botonomous Aug 29 '13 at 17:54
  • @ Mohamad Bataineh,At first I think all model in the same view but the view's content is different according to the return model's attribute of the controller.The requirement just like this, int the view left page,I show student,Fruit,and other model's name,when I click the student model name,in the view right page,it show the student model's attribute detail and I can also update the student student model's attribute value .when I click the Fruit model name,in the view right page,it show the Fruit model's attribute detail and I can also update the Fruit model's attribute value . – flower Aug 29 '13 at 18:07
  • @Adam,If my project have more than 10 models,means that I have to prepaire more than 10 views.It seems unrealistic,especially when I want to add a new model type to database but the site been published without this new model view. – flower Aug 29 '13 at 18:13
  • @Dunbar,Use a dynamic model type,Can you give me a example? – flower Aug 29 '13 at 18:15
  • I edited your question. Do not use images for your code. I replaced the image in your question with text. – ataravati Aug 29 '13 at 18:42

1 Answers1

1

Here's a simple example that shows how to do this using a dynamic model.

Firstly, I setup a couple of classes to represent the different examples of models you provided above:

public class Student
{
    public string Name { get; set; }
    public string Sex { get; set; }
    public string Address { get; set; }
}

public class Fruit
{
    public decimal Price { get; set; }
    public decimal Weight { get; set; }
}

Next, I created a DisplayTemplate for each type, like so:

@model Fruit

<p>Fruit template</p>

@Html.DisplayFor(m => m.Price)
@Html.DisplayFor(m => m.Weight)

@model Student

<p>Student template</p>

@Html.DisplayFor(m => m.Name)
@Html.DisplayFor(m => m.Sex)
@Html.DisplayFor(m => m.Address)

Now for the fun part. I created a view model to hold the dynamic model whilst also supplying a field to get the underlying type of the model:

public class ViewModel
{
    public dynamic Model { get; set; }
    public Type ModelType { get; set; }
}

That allows us to do 2 things:

  1. To assign an arbitrary type to Model.
  2. Use ModelType as a way to control which DisplayTemplate should be invoked for the model.

Therefore, your view would look something like the following:

@model ViewModel

@Html.DisplayFor(m => m.Model, Model.ModelType.ToString())

As you can see, this overload of Html.DisplayFor allows us to specify the template name, which is what the second parameter represents.

Finally, I created a quick action method to test this.

Firstly, for the Student type:

public ActionResult Index()
{
    var model = new ViewModel();
    model.ModelType = typeof(Student);
    model.Model = new Student { Name = "John", Sex = "Male", Address = "asdf" };

    return View(model);
}

Secondly, for the Fruit type:

public ActionResult Index()
{
    var model = new ViewModel();
    model.ModelType = typeof(Fruit);
    model.Model = new Fruit { Price = 5, Weight = 10 };

    return View(model);
}

Both gave the desired output.

John H
  • 14,422
  • 4
  • 41
  • 74