3

Assume I have a page (View) that takes a certain ViewModel:

@model IEnumerable<MyProject.ViewModels.MyViewModel>

In this page, I have a form that posts data through another ViewModel (let's call it a PostModel):

@using (Html.BeginForm("Order", "Order", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Give your order info</h4>
    <hr />
    @Html.ValidationSummary()
    <div class="form-group">
        <label for="Order.Name" class="col-md-2 control-label">Name:</label>

        <div class="col-md-10">
            @Html.TextBox("Order.Name", null, new { @class = "form-control" })
            @Html.ValidationMessage("Order.Name")
        </div>
    </div>
    ...
}

This is processed on the controller in an Order HttpPost action method that takes an argument of my PostModel's type.

I can display validation messages in the style I have above. My question is, how (if possible) can I make this strongly typed for my PostModel? Something like:

@Html.TextBox<MyPostModel>(t => t.Order.Name, ...)
@Html.ValidationMessageFor<MyPostModel>(t => t.Order.Name)

Is this at all possible, without changing the ViewModel of the page?

2
  • Out of curiosity, why do you want this functionality? Is there some side-effect of doing it this way that makes you want to handle it differently? Commented Jun 27, 2014 at 11:58
  • @xDaevax - not really, I was mostly just curious. Commented Jun 27, 2014 at 12:16

3 Answers 3

3

you can simply use a different partial-view for that form and in that partial-view you can specify it to be of any type you want, in this case, as i see in your code example, Order

Lets say you have a model called Order with the following definition

public class Order
{
    public string Name { get; set; }
}

and also a partial-view called _MyPostPartialView.cshtml with its definition

@model Order

@using (Html.BeginForm("Order", "Order", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>Give your order info</h4>
    <hr />
    @Html.ValidationSummary()
    <div class="form-group">
        @Html.Label(m => m.Name, "Name:")

        <div class="col-md-10">
            @Html.TextBox(m => m.Name, null, new { @class = "form-control" })
            @Html.ValidationMessage(m => m.Name)
        </div>
    </div>
    ...
}

and you're done!

Sign up to request clarification or add additional context in comments.

Comments

0

try import javascript bellow in your view

jquery.validate.min.js
jquery.validate.unobtrusive.min.js

In your form view

@Html.LabelFor(model => model.ClientDocument[0].Number)
 @Html.TextBoxFor(model => model.ClientDocument[0].Number, new { @class = "form-control" })

In your controller

[HttpPost]
public ActionResult Create(YourViewModel model){
if (ModelState.IsValid)//to complete validate server side
}

In your ViewModel *Try use DataAnnotation

 [Display(Name = "Name of Field")]
    [Required(ErrorMessage="your message error")]        
    public string Name { get; set; }
    public DocumentViewModel[] ClientDocument { get; set; }

4 Comments

Wouldn't this mean my PostModel is duplicated for each element of my IEnumerable? I'd rather this didn't happen.
maybe, i forgot this detail @Html.ValidationMessageFor(model => model.Name)
In my opinion, ViewModels shouldn't be model-bound (depending on your implementation). If you have "display-only" properties in the ViewModel (ie: ShowHeader, HasCustomFooter, OnlineUserCount, and even nested view models of other types for partials, etc...) you would not want the default model binder to reflect over your view model and attempt to bind these things. It could be inefficient at best and at worst it could lead to unexpected side-effects.
@IVlad My answer is based in question posted, "Validation for ViewModels different from the page ViewModel", you can validate two kind different of ViewModel, just use DataAnnatotion, if you have another doubt, contact me. Hope solve your question
0

The simple answer is don't use a different view model for GET vs POST. There's no reason to. Anything you POST should be rendered through the view model used for the GET request. If you are for some reason posting something that was not initially on the view model used for the GET request, then frankly, stop it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.