Malphai
Malphai

Reputation: 317

Validating Form in ASP.NET MVC C#

So as the title says, I am doing everything to get this validation to work, with RegEx and all, but it just wont work. What am I doing wrong here?

You dont need to type any data at all at the form, you can still send an empty mail, and I dont want that...

Model:

using System.ComponentModel.DataAnnotations;

namespace DK_Design.Models
{
    public class SendMail
    {
        [Required]
        public string Name { get; set; }

        [Required]
        public string Email { get; set; }

        public string Number { get; set; }

        [Required]
        public string Message { get; set; }
    }
}

View:

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<div class="container">
    <div class="row">
        <div class="box">
            <div class="col-lg-12">
                <hr>
                <h2 class="intro-text text-center">
                    Kontakta
                    <strong>Oss!</strong>
                </h2>
                <hr>
            </div>
            <div class="col-md-8">

            </div>
            <div class="col-md-4">
                <p>
                    Telefon:
                    <strong>123.456.7890</strong>
                </p>
                <p>
                    Email:
                    <strong><a href="mailto:*****@live.se">*****@live.se</a><!--I am obviously blurring the email on purpose here. The email function itself works.--> </strong>
                </p>
                <p>
                    Address:
                    <strong>
                        3481 Melrose Place
                        <br>Beverly Hills, CA 90210
                    </strong>
                </p>
            </div>
            <div class="clearfix"></div>
        </div>
    </div>

    <div class="row">
        <div class="box">
            <div class="col-lg-12">
                <hr>
                <h2 class="intro-text text-center">
                    Skicka
                    <strong>Ett Meddelande</strong>
                </h2>
                <hr>
                @if (ViewData["Message"] != null)
                {
                    <div class="alert alert-success">Ditt e-mail har skickats!</div>
                }
                @if (ViewData["Message"] == null)
                {
                    <div class="alert alert-danger">Ditt e-mail kan inte skickas!</div>
                }
                <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugiat, vitae, distinctio, possimus repudiandae cupiditate ipsum excepturi dicta neque eaque voluptates tempora veniam esse earum sapiente optio deleniti consequuntur eos voluptatem.</p>
                <form class="form-wrapper" id="contact-form" method="post" role="form" novalidate>
                    <div class="form-group">
                        <div class="row">
                            <div class="form-group col-lg-4">
                                <label for="name">
                                    Namn *
                                </label>
                                <input type="text" id="name" name="name" class="form-control" data-errmsg="Name is required."
                                       placeholder="Ditt Namn" required />
                            </div>
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="row">
                            <div class="form-group col-lg-4">
                                <label for="email">
                                    Email *
                                </label>
                                <input type="text" id="email" name="email" class="form-control" data-errmsg="Email is required."
                                       placeholder="Ditt Email" required />
                            </div>
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="row">
                            <div class="form-group col-lg-4">
                                <label for="number">
                                    Telefonnummer
                                </label>
                                <input type="text" id="number" name="number" class="form-control"
                                       placeholder="Ditt Telefonnummer" />
                            </div>
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="row">
                            <div class="form-group col-lg-8">
                                <label for="message">
                                    Meddelande *
                                </label>
                                <textarea id="message" name="message" class="form-control" data-errmsg="Message is required."
                                          placeholder="Ditt Meddelande" rows="3" required></textarea>
                            </div>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-md-2 col-sm-2 offset2">
                            <input style="font-size: 20px" type="submit" id="sendMail" value="Skicka" class="btn btn-primary" />
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>
</div>

Controller:

using DK_Design.Models;
using System.Net.Mail;
using System.Web.Mvc;

namespace DK_Design.Controllers
{
    public class KontaktController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(SendMail input)
        {
            var mail = new MailMessage("*****", "*****");
            var client = new SmtpClient("smtp-mail.outlook.com");
            client.Port = 587;
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            client.UseDefaultCredentials = false;
            var credentials = new System.Net.NetworkCredential("*****", "*****");
            client.EnableSsl = true;
            client.Credentials = credentials;
            mail.Body = input.Name + " " + input.Email + " " + input.Number + " " + input.Message;
            mail.Subject = "Paket 1";
            client.Send(mail);

            ViewData["Message"] = mail;

            return View(mail);

            //Blurring the email information here too ofcourse.
        }
    }
}

I get the success message to pop up when email is sent, but not the other way around.

Upvotes: 1

Views: 3508

Answers (3)

wormwood
wormwood

Reputation: 135

As several people have said, since you're using data annotation (the [Required] tag in your viewmodel), the good news is that you don't have to add too much to fix your problem.

To prevent it from sending blank emails, add the following to your controller:

if(!ModelState.IsValid)
{
    throw some kind of error here or do something else and return
}

The ModelState will be valid only if the incoming data is not null, which will prevent the rest of the code from being reached (and sending the email). There's a tutorial here on ModelState that's worth reading. The tutorial also discusses adding custom validators, which you may find useful if you need validation outside the provided MVC data annotations.

I would recommend validation messages and checks, to provide feedback for your user as they enter information. Those can be added to your model in the same way the [Required] tag was added:

[Required]
[StringLength(8, ErrorMessage = "The input cannot be longer than 8 characters.")]
public string StringyThingie { get; set; }

You can also add regex here (since you've mentioned using it), along with a validation message:

[Required]
[RegularExpression(@"^\d{0,4}+.\d{0,8}$", ErrorMessage = "Entry must be in the form of a decimal with no more than eight places to the right of the period.")]
public Decimal DecimalThingie { get; set; }

As a side note, if you want to check the validity of your regex before using it, Visual Studio has several built in tools that you can fetch through Nuget.

You would add the validation check/message directly to your view, in the form group for the user input:

 <div class="form-group">
    @Html.LabelFor(model => model.Field, htmlAttributes: new { @class = "control-label col-md-2"})
        <div class="col-md-10">
            @Html.EditorFor(model => model.Field, new { htmlAttributes = new { @class = "form-control"}}
            @Html.ValidationMessageFor(model => model.Field, "", new { @class = "text-danger"})
        </div>
  </div>

The html helper ValidationMessageFor will look at your model and grab the message you've listed as being for validation and will display it when the user attempts to post the page. Along with the other data annotation on your model variables and a ModelState check, it will prevent the user from going forward until the fields have content that meets your checks and prevent the rest of the controller method from executing in the event that something null gets past your checks.

You'll also want to add the following to your view, to provide a summary of validation failures (you should customize the arguments in it):

@Html.ValidationSummary(true, "", new { @class = "text-danger"})

You don't want to return the View at the end of your method--you should be using the RedirectToAction method:

return RedirectToAction("YourMethodHere", "YourControllerHere", "YourRouteDataHere");

The RedirectToAction command explicitly forces execution through a view controller.

Data annotations are pretty flexible, and using them will cause you to write comparatively less code than trying to write all those checks on incoming data yourself. The documentation can be found in the MSDN documentation and is built into the MVC system.

For greater control over what it does during the error process for errors inside the MVC system (not the Html errors), you can override the MVC method OnException, but it will considerably complicate your coding process. A good tutorial on how and why can be found here.

My advice to you on that issue, however, would be to take advantage of the Elmah package instead of trying to write that yourself. Elmah can be grabbed via the built-in Nuget package manager using the following command:

PM> Install-Package Elmah.MVC

Installing that will allow easier error logging and management, and allows considerable customization of that process without having to manage the filters and routing on your own.

Upvotes: 1

Shyju
Shyju

Reputation: 218782

Your view model is decorated with Required data annotations. So you can use the inbuilt model validation.

[HttpPost]
public ActionResult Index(SendMail input)
{
  if(!ModelState.IsValid)
      return View(input);     
   //Your existing code here which sends email 

}

Make sure you have the relevant code for showing the vlaidation messages in your view. You may use the ValidationSummary or/and ValidationFor helper methods as needed. You may use the html helper methods to render the input fields as well. The helpers will generate the markup needed to show validation error messages.

@model SendMail    
@using(Html.BeginForm())
{
      @Html.LabelFor(s=>s.Name)
      @Html.TextBoxFor(s=>s.Name)
      @Html.ValidationMessageFor(t => t.Name)

      @Html.LabelFor(s=>s.Email)
      @Html.TextBoxFor(s=>s.Email)
      @Html.ValidationMessageFor(t => t.Email)

      @Html.LabelFor(s=>s.Number)
      @Html.TextBoxFor(s=>s.Number)
      @Html.ValidationMessageFor(t => t.Number)

      @Html.LabelFor(s=>s.Message)
      @Html.TextAreaFor(s=>s.Message)
      @Html.ValidationMessageFor(t => t.Message)

      <input type="submit" />
 }

Also i suggest you to follow the PRG pattern(Post-Redirect-GET). So instead of returning to the same view ,you will redirect to another GET action.

return RedirectToAction("EmailSent");

Upvotes: 0

Steve
Steve

Reputation: 11963

to use client side validation (jquery val) you should consider using the build in function

@Html.TextBoxFor(m => m.Name)

and similarly for other properties.

This will stop the user from submitting the form if they are empty

Then on the server side you want to do

if(!ModelState.IsValid)
      return View(input); 

to stop the server from sending the email if its not valid

Upvotes: 0

Related Questions