0

I have a Main ViewModel class. This Main ViewModel contains a "partial" class.

The "partial" class has a "partial" view.

In my controller, I am using the "Main ViewModel" class and initializing a "Main View". This "Main View" contains a "partial view" which is based of the "partial class".

My problem is, when I edit/enter values in this partial view controls and then submit the "Main View" back to the controller, the newly entered values are not coming in. I was expecting the data to be bound to the "Partial View" when I called it from the main view like.

@Html.Partial("_TestPartial", Model.SomeTestInfo)

Am I missing something ? Please advise.

Here is my main controller.

public class TestController : Controller
{
    // GET: Test
    public ActionResult Index()
    {
        TestViewModel testViewModel = new TestViewModel();

        return View(testViewModel);
    }

    [HttpPost]
    public ActionResult Index(TestViewModel tvm)
    {
        string name = tvm.SomeTestInfo.TestName;
        int age = tvm.SomeTestInfo.TestAge;

        return View(tvm);
    }
}

Here is my ViewModel and the Partial Classes.

public class TestViewModel
{
    public TestPartial SomeTestInfo { get; set; }

    public TestViewModel()
    {
        SomeTestInfo = new TestPartial();
    }
}

public class TestPartial
{
    public string TestName { get; set; }
    public int TestAge { get; set; }

    public TestPartial()
    {

    }
}

Here is my Partial View

@model PartialViewEditTest.Models.TestPartial


@using (Html.BeginForm()) 
{
    
    <div class="form-horizontal">
        <h4>TestPartial</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.TestName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.TestName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.TestName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.TestAge, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.TestAge, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.TestAge, "", new { @class = "text-danger" })
            </div>
        </div>

    </div>
}


@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

=================================

Here is my main view which calls the partial view and submits back to the controller.

===================

    @model PartialViewEditTest.Models.TestViewModel

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>


@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <h4>TestViewModel</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        @Html.Partial("_TestPartial", Model.SomeTestInfo)

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

===================

Adam
  • 1,221
  • 4
  • 13
  • 27
  • The model in the main view is `TestViewModel` and you are expecting `TestViewModel` in the POST method. You partial is not generating inputs for `TestViewModel` - its generating them for `TestPartial`. Do not use `Partial() - you use `EditorFor()` and create a `EditorTemplate` for type of `TestPartial`. But if you do want to use a partial, refer the dupe –  Apr 05 '18 at 23:08
  • To make it an `EditorTemplate`, rename the partial to `TestPartial.cshtml` (i.e. to match the name of the class) and place it in the `/Views/Shared/EditorTemplates` folder, then its just `@Html.EditorFor(m => m.SomeTestInfo)` –  Apr 05 '18 at 23:42
  • I have more than one PartialViews in the page. If I use new ViewDataDictionary { TemplateInfo = new TemplateInfo { HtmlFieldPrefix = "CustomerContact" } }, it helps only the first partialview, other views are returning null. – Adam Apr 06 '18 at 00:29
  • As I stated - use EditorTemplates (but you could have done it using `HtmlFieldPrefix = "CustomerContact.SomeProperty"` –  Apr 06 '18 at 00:40
  • If use @html.Editorfor, then the validation error text colors are black in the partial model properties. I want it red color. That's the reason I created partial views so I can customize the look the way I want. – Adam Apr 06 '18 at 04:42
  • That has nothing at all to do with using `@Html.EditorFor()` - its a css issue. And its still a partial view anyway - its just called by `EditorFor()` which generates identical html except for the `name` attribute - which `EditorFor()` generate correctly –  Apr 06 '18 at 04:45
  • And you also have nested forms which is invalid html and not supported. You need to remove the `@using (Html.BeginForm())` and the `@Html.ValidationSummary()` from the partial –  Apr 06 '18 at 04:47
  • You also need to remove the `@section Scripts { ... }`. Apart from the fact that scripts should never be in partials, `sections` are not supported in partials (which is fortunate for you, otherwise you would have duplicated `jqueryval`) –  Apr 06 '18 at 04:54
  • I guess PartialView is not suitable for what I am doing. I will go with your idea of using Editortemplate. Thanks for all the help. – Adam Apr 06 '18 at 05:28
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/168368/discussion-between-stephen-muecke-and-adam). –  Apr 06 '18 at 05:36
  • Sorry, wasn't able to join the chat. I got the idea. Appreciate your help. Thank you. – Adam Apr 06 '18 at 15:59

0 Answers0