35

I am trying to generate such HTML

    <form action="/some/process" method="post">
        <input type="hidden" name="foo.a" value="aaa"/>
        <input type="hidden" name="bar.b" value="bbb"/>
        <input type="submit" />
    </form>

so it can be processed by this Action:

    public ActionResult Process(Foo foo, Bar bar)
    {
        ...
    }

Given the Action code

    public ActionResult Edit()
    {
        ViewData["foo"] = new Foo { A = "aaa" };
        ViewData["bar"] = new Bar { B = "bbb" };

        return View();
    }

what should I write in Edit.aspx view? I don't want to write names 'foo.a' and 'bar.b' manually.

alex2k8
  • 42,496
  • 57
  • 170
  • 221

4 Answers4

43

String-indexed ViewData is bad. What you probably want to do is make a little wrapper class for your multi-variable view data and pass that to a strongly typed view. IE:

public class FooBarViewData
{
   public Foo Foo {get; set;}
   public Bar Bar {get; set;}
}
public ActionResult Edit()
{
   FooBarViewData fbvd = new FooBarViewData();
   fbvd.Foo = new Foo(){ A = "aaa"};
   fbvd.Bar = new Bar(){ B = "bbb"};
   return View(fbvd);
}

Then your view is just strongly typed to FooBarViewData and you can call members of that object using the Model property.

Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
Wyatt Barnett
  • 15,573
  • 3
  • 34
  • 53
11

You have a couple of choices. First, you can reference them from ViewData and use an HtmlHelper extension. Or you could create a view-specific model and use a strongly-typed viewpage for Edit.aspx.

public class EditModel
{
    public Foo foo { get; set; }
    public Bar bar { get; set; }
}

public ActionResult Edit()
{
    var model = new EditModel();

    model.foo = new Foo { A = "aaa" };
    model.bar = new Bar { B = "bbb" };

    return View( model );
}

(Edit.aspx is of type ViewPage<EditModel>)

Either way, the HtmlHelper extension will pick up any initial values.

<form action="/some/process" method="post">
     <%= Html.Hidden( "foo.A" ) %>
     <%= Html.Hidden( "bar.B" ) %>
</form>
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
0

The solution above may be outdated. This solution seems to work for ASP.Net MVC5+.

You're going to have to use the ViewModel method. This is an excellent tutorial that you can check out.

http://tutlane.com/tutorial/aspnet-mvc/how-to-use-viewmodel-in-asp-net-mvc-with-example

You are going to have to join multiple models into one ViewModel and grab all the properties from each models you want to use into the ViewModel.

BUT, it is HIGHLY advised that you create a new Controller and a new View to accomodate the newly created ViewModel. Read the tutorial.

public class FooBarViewModel
{
   public string A {get; set;}  //Property for Foo
   public string B {get; set;}  //Property for Bar
}

public ActionResult Edit()
{
   FooBarViewModel fooBarVM = new FooBarViewModel();
   fooBarVM.A = "aaa";
   fooBarVM.B = "bbb";

   return View(fooBarVM);
}

But in this case, you should be able to pass the ViewModel into a different view. Just make sure you declare this similar directive correctly in the foobar.cshtml page.

@model FooBar.Models.FooBarViewModel
David Lee
  • 143
  • 1
  • 12
0

I was struggling for a while trying to get two models to work, and most of the answers I came across was meant for earlier versions of MVC.

I found the following tutorial works best for MVC 5 as suggested by David Lee:

http://tutlane.com/tutorial/aspnet-mvc/how-to-use-viewmodel-in-asp-net-mvc-with-example

I created a join and selected only the columns I needed from both Models.

I had it working with partial views

In view.cshtml

 @model IEnumerable<Test.Models.TestViewModel>
    ...
      @foreach (var item in Model)
                    {
                        <tr>
                            <td style="text-align:center;vertical-align:middle">
                                @Html.DisplayFor(modelItem => item.TestName)
...
Abdul G
  • 36
  • 1
  • 1
  • 5