开发者

Polymorphism and Strongly-typed Views in ASP.NET MVC

I have a problem where I have two forms that are identical except that the required fields are different. For example, let's say the forms have the same fields: X, Y, and Z. In Form #1, X is required, but in Form #2, Y is required.

So I created two view models, Form1 and Form2, with the same properties but with the Required attributes on 开发者_运维百科different properties. I then created an interface, let's call it IForm, that both models implement and built a View that is strongly typed on IForm.

The problem with that solution is that ASP.NET MVC 3 reads the attributes on IForm instead of the dynamic type of the object being passed to the view, that is Form1 or Form2, so I don't get the client side JavaScript field validation that I want.

I'm wondering if there's a solution other than creating a strongly-typed View for each view model.


I have put together a sample with what you described (I think) and I'm able to get it to work:

public class TestController : Controller
{
    public ActionResult Foo()
    {
        return View("IFoo");
    }

    [HttpPost]
    public ActionResult Foo(Foo foo)
    {
        if (!ModelState.IsValid)
            return View("IFoo", foo);

        return RedirectToAction("Foo");
    }

    public ActionResult Bar()
    {
        return View("IFoo");
    }

    [HttpPost]
    public ActionResult Bar(Bar bar)
    {
        if (!ModelState.IsValid)
            return View("IFoo", bar);

        return RedirectToAction("Bar");
    }
}

// The Interface - the Required attributes are not 
// on the interface, just the concrete classes
public interface IFoo
{
    string Name { get; set; }
    string Description { get; set; }
}

// Concrete Class 1 - Name is required
public class Foo : IFoo
{
    [Required(ErrorMessage="Name is required.")]
    public string Name { get; set; }

    public string Description { get; set; }
}

// Concrete Class 2 - Description is required
public class Bar : IFoo
{
    public string Name { get; set; }

    [Required(ErrorMessage = "Description is required.")]
    public string Description { get; set; }
}

I then defined a strongly typed view:

@model Test.Controllers.IFoo

<h2>Test</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>IFoo</legend>

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

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

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

When I browse to /test/foo and hit the Save, I get a validation error on Name.

When I browse to /test/bar and hit the Save, I get a validation error on Description.


Try partial form validation approach.

http://softwaredevelopmentsolutions.blogspot.com/2011/06/aspnet-mvc-3-partial-form-validation-on.html

Create custom action filter attribute. Decorate the action methods with it to ignore validation properties according to the forms.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜