John John
John John

Reputation: 1

Ajax.Beginform + Partial view + Model state are not working together

I have the following Create action method inside my ASP .NET MVC :-

 public ActionResult CreateVMNetwork(int vmid)
        {
            VMAssignIps vmips = new VMAssignIps()
            {
                TechnologyIP = new TechnologyIP() { TechnologyID = vmid},
                IsTMSIPUnique = true,
                IsTMSMACUnique = true
            };
            return PartialView("_CreateVMNetwork",vmips);
        }

Which will render the following partial view:-

    @model TMS.ViewModels.VMAssignIps

    @using (Ajax.BeginForm("CreateVMNetwork", "VirtualMachine", new AjaxOptions

    {
        InsertionMode = InsertionMode.InsertAfter,
        UpdateTargetId = "networktable",
        LoadingElementId = "loadingimag",
        HttpMethod= "POST"
    }))
    {
           @Html.ValidationSummary(true)
           @Html.HiddenFor(model=>model.TechnologyIP.TechnologyID)
        <div>
<span class="f">IP Address</span> 

@Html.EditorFor(model => model.TechnologyIP.IPAddress)
@Html.ValidationMessageFor(model => model.TechnologyIP.IPAddress)                                              

   <input type="CheckBox" name="IsTMSIPUnique" value="true" @(Html.Raw(Model.IsTMSMACUnique ? "checked=\"checked\"" : "")) /> | 
 <span class="f"> MAC Address</span>       
@Html.EditorFor(model => model.TechnologyIP.MACAddress)
@Html.ValidationMessageFor(model => model.TechnologyIP.MACAddress)                                              

 <input type="CheckBox" name="IsTMSMACUnique" value="true" @(Html.Raw(Model.IsTMSMACUnique ? "checked=\"checked\"" : "")) />

</div>   
           <input type="submit" value="Save" class="btn btn-primary"/>
    }

Inside the following main view, after clicking on the Ajax.actionlink:-

@Ajax.ActionLink("Add Network Info", "CreateVMNetwork","VirtualMachine",
    new { vmid = Model.VirtualMachine.TMSVirtualMachineID },
    new AjaxOptions {
 InsertionMode = InsertionMode.Replace,
 UpdateTargetId = "AssignNetwork"  ,
 LoadingElementId = "progress"


}
)
    </p>
<p><img src="~/Content/Ajax-loader-bar.gif" class="loadingimage" id="progress" /></p>
<div id ="AssignNetwork"></div>

Then when clicking on the “Save” button it will call the following action method:-

[HttpPost]
        public ActionResult CreateVMNetwork(VMAssignIps vmip)
        {
if (ModelState.IsValid)
 {
try
{
repository.InsertOrUpdateVMIPs(vmip.TechnologyIP,User.Identity.Name);
repository.Save();
return PartialView("_networkrow",vmip);
 }
catch (Exception ex)
{
ModelState.AddModelError(string.Empty, "Error occurred: " + ex.InnerException.Message);
}}
return PartialView("_CreateVMNetwork", vmip);

}

When will render the following partial view _networkrow:-

@model TMS.ViewModels.VMAssignIps
<tr id="@Model.TechnologyIP.ID">
    <td> @Model.TechnologyIP.IPAddress</td> 

    <td>@Model.TechnologyIP.MACAddress</td>
    <td>@Ajax.ActionLink("Delete",
 "DeleteNetworkInfo", "VirtualMachine",
new { id = Model.TechnologyIP.ID },

new AjaxOptions
{ Confirm = "Are You sure You want to delete (" + Model.TechnologyIP.IPAddress + ")" + "( " + Model.TechnologyIP.MACAddress + ").",
    HttpMethod = "Post",

    OnSuccess = "deletionconfirmation",
    OnFailure = "deletionerror"
})</td>
    </tr>

All the above will work fine unless a model state error or an exception occurred , then in this case the table will be updated with the partial view and the model state will be displayed under the table with the fields. But I need to display the model state error on the same original view. So that I need the Ajax.begin form to update the table only if no exception or model state errors occured, and to display an error message inside the original partial view, not under the table.

Can anyone advice on how to solve this issue?

Upvotes: 1

Views: 963

Answers (2)

JTMon
JTMon

Reputation: 3199

Where is networktable defined? Remember that even if there is an exception (since you have caught it) or ModelState error, the ajax response will come back with status 200 and the OnSuccess will be executed. In the case of the save button, the returned response from the server will be inserted after the html of whatever networktable contains already. If you want special action to be taken when there is a failure, you have to change the response status on the server and catch it through a function on the client side called by OnFailure on the ajax form.

Upvotes: 0

Amin Saqi
Amin Saqi

Reputation: 18977

I don't get your question clearly, however I think you should place a <div> into your view where you want to show errors.

Then, if you got some errors on your processing, push some error messages through ViewBag to the model.

So, your action method will become like this:

[HttpPost]
public ActionResult CreateVMNetwork(VMAssignIps vmip)
{
if (ModelState.IsValid)
{
    try
    {
        repository.InsertOrUpdateVMIPs(vmip.TechnologyIP,User.Identity.Name);
        repository.Save();
        return PartialView("_networkrow",vmip);
    }
    catch (Exception ex)
    {
        ViewBag.ErrorMessage = "Some messages...";
        // also any other info you like
    }
}

return PartialView("_CreateVMNetwork", vmip);

}

And that in your view like this:

<div>
    <p>@ViewBag.ErrorMessage</p>
</div>

So, if you you got some errors, they'll be shown in that

Upvotes: 1

Related Questions