C# – ASP.NET MVC Validation in Partial View and return to Parent view

asp.netasp.net-mvcasp.net-mvc-4c

My Background

I am working on first serious project using ASP.NET MVC 4. I am working on web development since classic ASP days and have got good hold on Webforms. MVC is very exciting and am doing good progress. But now I am in a situation where I need help on this forum.

Query background

I have a parent view and inside it there is a partial view. Partial view contains a form and submit button. The partial view has its own local view model and that view model is one of the properties of the Parent view model.

In case the validations on partial views fail, I want to, show the parent view as it is and highlight invalid fields in partial view.

The code is not breaking anywhere but when there is a validation error, somehow, i am not finding right way to show parent view with initialised model passed to it. And of course, to highlight the errors in partial view.

Any help would be appreciated. Thanks.

Code looks like following:

View Models:

public class ParentViewModel
{
    public int TitleId { get; set; }
    public string Name { get; set; }
    public ChildViewModel Child { get; set; }
}

public class ChildViewModel
{
    [Required]
    public decimal Rating { get; set; }        

    [Required]
    [StringLength(500)]
    [Display(Description = "Review")]
    [RegularExpression("([a-zA-Z0-9 .&'-]+)", ErrorMessage = "Enter only alphabets and numbers of First Name")]
    public string ReviewText { get; set; }
}

Controller

public class TestController : Controller
{
    public ActionResult Index()
    {
        var model = new ParentViewModel()
                        {
                            TitleId = 1,Name = "Parent name",
                            Child = new ChildViewModel()
                                        {
                                            Rating = 2.5M, ReviewText = "Its a must watch!"
                                        }
                        };
        return View("Index", model);  
    }

    [HttpPost]
    public ActionResult SubmitReview(ChildViewModel model)
    {
        if (ModelState.IsValid )
        {
            return View("_child", model);
        }

        ModelState.AddModelError("", "Some Error.");
        return View("_child", model);
    }
}

Parent View

@model ParentViewModel
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <title>Index</title>
</head>
<body>
    <div>
        @Model.TitleId, @Model.Name        
    </div>
    <div>
        @Html.Partial("_child", Model.Child)
    </div>
</body>
</html>

Partial View (_child.cshtml)

@model ChildViewModel
@using (Html.BeginForm("SubmitReview", "Test"))
{
    @Html.ValidationSummary(true)

    @Html.TextBoxFor(m => m.Rating)     @Html.ValidationMessageFor(m => m.Rating)
    @Html.TextBoxFor(m => m.ReviewText) @Html.ValidationMessageFor(m => m.ReviewText)
    <input type="submit" value="Log in" />
}

Best Answer

You need to show the parent view not the child one, so the action should look like:

[HttpPost]
    public ActionResult SubmitReview(ChildViewModel model)
    {
             var parentViewModel = write init code here;
            parentViewModel.ChildModel = model;

        if (ModelState.IsValid )
        {

            return View("Index", parentViewModel );
        }

        ModelState.AddModelError("", "Some Error.");
        return View("Index", parentViewModel );
    }