Harris Yer
Harris Yer

Reputation: 291

What is the proper way to submit data from Parent form with partial view MVC 4?

The Main Controller

public class TestPartialController : Controller
{
    //
    // GET: /TestPartial/

    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index(Main model)
    {
        HttpContext.Items.Add("MainModel", model); 
        return View();

    }

    public ActionResult PartialA()
    {
        return PartialView();
    }


    [HttpPost]
    public ActionResult PartialA(PartialA a)
    {
        if (HttpContext.Items["MainModel"] != null)
        {
            Main model =(Main) HttpContext.Items["MainModel"];
            model.PA = a;
        }
        return PartialView();

    }

    public ActionResult PartialB()
    {
        return PartialView();
    }

    [HttpPost]
    public ActionResult PartialB(PartialB b)
    {
        if (HttpContext.Items["MainModel"] != null)
        {
            Main model = (Main)HttpContext.Items["MainModel"];
            model.PB = b;
        }
        SubmitDatatoDB();
        return PartialView();
    }

    public void SubmitDatatoDB()
    {
        if (HttpContext.Items["MainModel"] != null)
        {
            Main model = (Main)HttpContext.Items["MainModel"];
            //SubmitDatatoDB
        }
    }

}

Models:-

namespace TestingMVC4.Models
{
public class Main
{
    public string Main1 { get; set; }
    public string Main2 { get; set; }
    public virtual PartialA PA { get; set; }
    public virtual PartialB PB { get; set; }
}

public class PartialA
{
    public string UserName { get; set; }
    public string UserID { get; set; }
}

public class PartialB
{
    public string UserNameB { get; set; }
    public string UserIDB { get; set; }
}
}

View :-

@model TestingMVC4.Models.Main

@{
ViewBag.Title = "Index";
}

<h2>Index</h2>

@using (Html.BeginForm()) {
@Html.ValidationSummary(true)

<fieldset>
    <legend>Main</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.Main1)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Main1)
        @Html.ValidationMessageFor(model => model.Main1)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.Main2)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Main2)
        @Html.ValidationMessageFor(model => model.Main2)
    </div>

    <div>
        @Html.Action("PartialA","TestPartial")
    </div>
     <div>
        @Html.Action("PartialB","TestPartial")
    </div>

    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>
}

@model TestingMVC4.Models.PartialA
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)

<fieldset>
    <legend>PartialA</legend>

    <div class="editor-label">
        @Html.LabelFor(model => model.UserName)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.UserName)
        @Html.ValidationMessageFor(model => model.UserName)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => model.UserID)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.UserID)
        @Html.ValidationMessageFor(model => model.UserID)
    </div>


</fieldset>
} 

Mine Question is if doing like this, the Index of HTTPPOST of main view will fire first. than follow by Partial view A and Partial View B. In this case I need to store the data in HttpContext.Items and call the submit to Database in the last Partial view B.

What I want is fire the Partial view A and B first, and store the data into Main View's model and call the SubmitDatatoDB function in Main View's POST Action.

Upvotes: 0

Views: 6813

Answers (2)

Harris Yer
Harris Yer

Reputation: 291

Figure out 2 method to achieve mine goal

1) Passing the main model to each partial view, sample of partial view :-

@model TestingMVC4.Models.Main
//@model TestingMVC4.Models.PartialA
<fieldset>
    <legend>PartialA</legend>
    <div class="editor-label">
        @Html.LabelFor(model => model.PA.UserName)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.PA.UserName)
        @Html.ValidationMessageFor(model => model.PA.UserName)
    </div>
    <div class="editor-label">
        @Html.LabelFor(model => model.PA.UserID)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.PA.UserID)
        @Html.ValidationMessageFor(model => model.PA.UserID)
    </div>
</fieldset> 

disadvantages of this method is the partial view is tight to other view.

2) convert all partial view to become templates helpers :- reference from http://lostechies.com/jimmybogard/2011/09/07/building-forms-for-deep-view-model-graphs-in-asp-net-mvc/

this second method is reuse able because it used it own model binding rather than model from parent, for example :-

@model TestingMVC4.Models.ProductEditModel
@{
    ViewBag.Title = "Index";
}
<p>
    @Html.LabelFor(m => m.Name)
    @Html.TextBoxFor(m => m.Name)
</p>
@Html.EditorFor(m => m.Price)    


@model TestingMVC4.Models.PriceEditModel
<p>
    @Html.LabelFor(m => m.Currency)
    @Html.TextBoxFor(m => m.Currency)
</p>
<p>
    @Html.LabelFor(m => m.Value)
    @Html.TextBoxFor(m => m.Value)
</p>

Upvotes: 2

forseta
forseta

Reputation: 89

You need to change your binds to get PartialModelA to populate MainModel and ensure that Partial View A is posting back to and action on the Main Controller

Something like this:

@using (Html.BeginForm("MainAction", "MainController")) {

<fieldset>
    <legend>PartialA</legend>

    <div class="editor-label">
        @Html.Label("UserName", model.UserName)
    </div>
    <input type="submit" />

</fieldset>
}

Notice the Action and Controller added to the form and the change of LabelFor to use just Label.

Upvotes: 1

Related Questions