1

I'm beggining to learn Asp.net and C# for about a week. Until now, I've been developing in PHP and Symfony so this is quite a big transition for me. I'm learning Asp.net from a book ASP.NET MVC 4 in Action.

I'm trying to validate a model but I can't find anything online that will help a newbie like me. A model validates a contact form with name, email and a message. Simple, right?. Not for me.

This is the model...

public class ContactModel
{
    [Required(ErrorMessage = "The name has to be provided, even a fictional one")]
    public string Name { set; get; }

    [Required(ErrorMessage = "Email address has to be provided, even a invalid one")]
    [DataType(DataType.EmailAddress)]
    public string Email { set; get; }

    [Required(ErrorMessage = "Don't be lazy. Write a message")]
    [DataType(DataType.MultilineText)]
    public string Message { set; get; }
}

I have a controller called ContactController. It has these actions...

public ActionResult Contact()
{
    ContactModel contactModel = new ContactModel();
    return View(contactModel);
}

[HttpPost]
public ViewResult SaveModel(ContactModel model)
{
    return View(model);
}

Also, here is a Razor template that shows the model in the UI.

<div class="UI__Main  Main__Contact">
<h1 class="UI__Main--SectionHeader">Contact the administrators of Life</h1>

    @using (Html.BeginForm("SaveModel", "Contact", FormMethod.Post, new { @class="Form  Form__Contact" }))
    {
        <div class="Form__Row">
            @Html.LabelFor(model => model.Name, new { @class="Form__Label" })
            @Html.TextBoxFor(model => model.Name, new { @class="Form__TextType  Form__TextInput" })
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="Form__Row">
            @Html.LabelFor(model => model.Email, new { @class = "Form__Label" })
            @Html.TextBoxFor(model => model.Email, new { @class = "Form__TextType  Form__TextInput" })
        </div>

            <div class="Form__Row">
                @Html.LabelFor(model => model.Message, new { @class="Form__Label" })
                @Html.TextArea("Message", new { @class = "Form__TextType  Form__TextArea" })
            </div>

        <div class="Form__Row  Submit__Row">
            <input id="Submit__Button" type="submit" value="Send" />
        </div>
    }

When the user submits the form, the form would have to go to SaveModel action in ContactController but action attribute of <form> is blank action="" so i don't think it's even going to Save Model. Also, validation messages are not displayed. I tried the @Html.ValidationMessageFor but that only displays text even when i don't submit the form.

I don't even know what the problem is here let alone find it.

If anyone has any suggestions, tutorials, articles or something like that about creating form in asp.net mvc 4 and razor, please give it to me.

I've read this article but that doesn't solve my problem. I also found this Stack question and this Stack question but as i said, I'm a newbie and I really don't understand the problems in those questions.

EDIT:

Here are the routes of the app...

routes.MapRoute(
    name: null,
    url: "",
    defaults: new { controller = "Home", action="Index" }
);

routes.MapRoute(
    name: null,
    url: "contact",
    defaults: new { controller = "Contact", action = "Contact" }
);
Community
  • 1
  • 1
Mario Legenda
  • 749
  • 1
  • 11
  • 24
  • Have you implemented any extra routes, besides the default one? – Tobias Nov 07 '14 at 13:48
  • I've made an edit. ContactController/ContactAction is called with a static route but , my guess is that model validation has to go to another action, which is SaveModel action in ContactController. – Mario Legenda Nov 07 '14 at 13:53

1 Answers1

1

your action stays empty because the MVC framework can not resolve an url for the given controller+action. You have to explicitly define an url in the routing table:

routes.MapRoute(
    name: null,
    url: "contact/send-form",
    defaults: new { controller = "Contact", action = "SaveModel" }
);

Or you can alternatively generate a generic fallback route

routes.MapRoute(
    name: null,
    url: "{controller}/{action}",
    defaults: new { controller = "Home", action = "Index" }
);

which will result in that all your controller/actions are available as direct urls.

Alternatively; you can also use attribute routing so your routes are defined directly at the actions, less looking here & there. To do so you have to:

  • add routes.MapMvcAttributeRoutes(); in the RegisterRoutes.cs
  • append attributes to your actions [Route("contact")]

You can also re-use the same route if the http method differs:

[HttpGet]
[Route("contact"}
public ActionResult Contact()
{
    ContactModel contactModel = new ContactModel();
    return View(contactModel);
}

[HttpPost]
[Route("contact")]
public ViewResult Contact(ContactModel model)
{
  if(ModelState.IsValid){
    //persist your contact form, redirect somewhere
  }
  return View(model);//re-render the form with error messages
}
Mark van Straten
  • 9,287
  • 3
  • 38
  • 57
  • YES. That was it. Thank you very much. The error message displayes nicely. – Mario Legenda Nov 07 '14 at 14:06
  • Usage a `route` attributes are only essential if you have to use in a case when url must have other form than wrote in Route map. Otherwise is reccomended to avoid this parameter. This way determines rigorous an approach to your project. – Marek Woźniak Nov 07 '14 at 14:18