Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Form for a different model than the view page in ASP.NET MVC 3

I have Results page that contains an signup form. I'm trying to use client-side validation on the email model, but I can't because the model type is different than the type I'm posting.

class Results
{
     ... // some results data to display
}

class EmailSignup
{
    public virtual int Id { get; set; }

    [Required(ErrorMessage = "Please enter your email.")]
    [DataType(DataType.EmailAddress)]
    [RegularExpression(@"^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$", ErrorMessage = "Please enter a valid email address.")]
    public virtual string Email { get; set; }
}

Results.cshtml

@model MyApp.Results
[display results]
...
@using (Html.BeginForm("SubmitEmail", "AnalysisResults", FormMethod.Post))
{
     <fieldset>
     @Html.TextBoxFor( model => model.???? )
     </fieldset>
}

The type I want the user to submit is EmailSignup, not Results.

like image 952
Wesley Tansey Avatar asked Mar 27 '11 01:03

Wesley Tansey


People also ask

Can we have two model in view in MVC?

In MVC we cannot pass multiple models from a controller to the single view.

Can we use 2 models in a view?

You can use multiple models in a single view by creating a common model for all the models that are to be used in a single view. To achieve this, refer to the following steps. First, create a new model (common for all models) and refer all other models that are to be used in the same view.

How do you specify a model in view?

To declare the model type, use the @model directive. Show activity on this post. Note the lowercase @model since uppercase prints the value of the Model property.


4 Answers

Move the form to a partial view that takes an EmailSignup model.

like image 84
SLaks Avatar answered Oct 16 '22 20:10

SLaks


This can be done quite easily. You just have to do it like this:

var contactModel = new ContactModel();
@Html.TextBoxFor(m => contactModel.Title)
@Html.ValidationMessageFor(m => contactModel.Title)

The validation works like a charm.

like image 44
Daniel Avatar answered Oct 16 '22 20:10

Daniel


I have find out 2 more ways

  1. Override the Name attribute for TextBoxFor and set it as the property name.
    var formModel = new ForgotPasswordFormModel();
    @Html.TextBoxFor(m => formModel.UsernameOrEmail, new { Name = "UsernameOrEmail" })
  1. Specify the same exact model name as the post method parameter.
    var formModel = new ForgotPasswordFormModel();
    @using (Html.BeginForm("ChangePassword", "LoginSurface")
    {
       @Html.TextBoxFor(m => formModel.UsernameOrEmail)
    }
    ...
    public virtual ActionResult ChangePassword(ForgotPasswordFormModel formModel)
like image 3
Pavlo Avatar answered Oct 16 '22 18:10

Pavlo


You could create another HtmlHelper like this

var emailSignupHtml = new HtmlHelper<EmailSignup>(Html.ViewContext, new ViewDataContainer<EmailSignup>(new EmailSignup()));

and use it like this

@emailSignupHtml.TextBoxFor(m => m.Email)

For the ViewDataContainer I use following helper class

public class ViewDataContainer<TModel> : ViewDataDictionary<TModel>, IViewDataContainer
{
   public ViewDataContainer(TModel model) : base (model)
   {
      ViewData = new ViewDataDictionary(model);
   }

   public ViewDataDictionary ViewData { get; set; }
}
like image 3
Sven Avatar answered Oct 16 '22 18:10

Sven