0

I'm completely new in Asp.net MVC

I want to fill a form and post it to data base but my model Binder validation is false . and my Errors which I have in my model doesn't show

I'm sorry because I don't know what is the problem I couldn't shorten it:

here is my model:

public class Request
{
    //pkey
    public virtual int Id { get; set; }
    //Fkey
    public virtual int TourId { get; set; }

    [Required]
    [MaxLength(150, ErrorMessageResourceType = typeof(ErrorResource), ErrorMessageResourceName = "CheckLenght")]
    public virtual string FirstName { get; set; }


    [Required]
    [MaxLength(150, ErrorMessageResourceType = typeof(ErrorResource), ErrorMessageResourceName = "CheckLenght")]
    public virtual string LastName { get; set; }

    [Required]
    [EmailAddress(ErrorMessageResourceType = typeof(ErrorResource), ErrorMessageResourceName = "Email")]
    [MaxLength(150, ErrorMessageResourceType = typeof(ErrorResource), ErrorMessageResourceName = "CheckLenght")]
    public virtual string Email { get; set; }

    [Required]
    public virtual string Phone { get; set; }

    [MaxLength(100000000, ErrorMessageResourceType = typeof(ErrorResource), ErrorMessageResourceName = "CheckLenght")]
    public virtual string Comment { get; set; }


    public virtual bool FrequentTraveler { get; set; }

    [Required]
    [Range(1, 500000)]
    public virtual int TravelersCount { get; set; }


    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
    public virtual string Date { get; set; }


    public virtual bool ContactTimePreference { get; set; }

    [MaxLength(150, ErrorMessageResourceType = typeof(ErrorResource), ErrorMessageResourceName = "CheckLenght")]
    public virtual string Country { get; set; }


    public virtual bool Archived { get; set; }

and this is my form in view :

@using (Html.BeginForm("Create", "Request"))
{
  <div class="form-group">
   <input  type="hidden" name="TourId" value="4"/>
  </div>

 <div class="form-group">
 @Html.EditorFor(model => model.Request.FirstName, new { htmlAttributes = new { @class = "form-control" } })
 @Html.ValidationMessageFor(model => model.Request.FirstName, "", new { @class = "text-danger" , placeholder = "FirstName" })

 </div>



<div class="form-group">
 @Html.EditorFor(model => model.Request.LastName, new { htmlAttributes = new { @class = "form-control" } })
 @Html.ValidationMessageFor(model => model.Request.LastName, "", new { @class = "text-danger" })
</div>


<div class="form-group">                                       
@Html.EditorFor(model => model.Request.Email, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Request.Email, "", new { @class = "text-danger" })
</div>

<div class="form-group">
 @Html.EditorFor(model => model.Request.Phone, new { htmlAttributes = new { @class = "form-control" } })
 @Html.ValidationMessageFor(model => model.Request.Phone, "", new { @class = "text-danger" })
</div>


 <div class="form-group ft">
 @Html.EditorFor(model => model.Request.FrequentTraveler)
 @Html.ValidationMessageFor(model => model.Request.FrequentTraveler, "", new { @class = "text-danger" })
    </div>


<div class="form-group">
   <input type="hidden" name="TravelersCount" value="3" />
</div>

  <div class="form-group">
    <input type="hidden" name="TravelersCount" value="3" />
  </div>



}

I omit some of the form groups which they allow to be null for shorthand.

and this is my create action in Request controller:

 [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create([Bind(Include = "Id,TourId,FirstName,LastName,Email,Phone,Comment,FrequentTraveler,TravelersCount,Date,ContactTimePreference,Country,Archived")] Request request)
    {
        if (ModelState.IsValid)
        {
            db.Requests.Add(request);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View();
    }

I appreciate if some one tell me what is the problem to make my request object valid.and if its possible what to do to send Errors to user when for example they put null in first name which its required with server.

neda Derakhshesh
  • 1,103
  • 2
  • 20
  • 43
  • 1
    Start by removing your `[Bind]` attribute. –  Jun 28 '16 at 11:02
  • 1
    The `ModelState` object will tell you exactly what is wrong, take a look in there for the reason why it is not valid. – DavidG Jun 28 '16 at 11:03
  • @DavidG .thanks for you'r care. where can I check my `ModelState`? – neda Derakhshesh Jun 28 '16 at 11:06
  • @StephenMuecke .thanks for you'r care . I change it to this `public ActionResult Create( Request request)` but no diffrence – neda Derakhshesh Jun 28 '16 at 11:19
  • As @DavidG as stated, debug your code and check the values in `ModelState` - it will tell you what the errors are. But the first thing you need to learn when editing is to use a [View Model in MVC](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc). Almost none of your properties will bind because the model in the view is not `@model Request` but the model in the POST method is - they need to be the same. –  Jun 28 '16 at 11:24
  • @StephenMuecke really thank you. I debug and Checked my model state . the problem was for those tags which I didn't use helper . it is valid now. but I need to read more about the point I should use same name for my model and also my post method. really thank you. – neda Derakhshesh Jun 28 '16 at 11:43
  • if its possible for you please answer this question that I can accept it . model state checking really helped. thanks – neda Derakhshesh Jun 28 '16 at 11:52

2 Answers2

2

ModelState will be invalid because your view is generating form controls for a model which is different from the model that you expect in the POST method. For example

@Html.EditorFor(model => model.Request.FirstName, ...)

is generating

<input type="text" name="Request.FirstName" .... />

but the model in the POST method is Request which does not have a property named Request - it only has one named FirstName so binding fails and ModelState is invalid because of the [Required] validation attribute.

In order to bind to a Request model, the html would need to be

<input type="text" name="FirstName" .... />

In addition, your [Bind] attribute is also excluding the values from correctly binding since it does include "Request".

Remove the [Bind] attribute (you seem to be wanting to bind everything anyway which is the default) and either change the model in the POST method to match the model you declared in the view, or use the Prefix property of BindAttribute

public ActionResult Create([Bind(Prefix= "Request")] Request model)

and finally delete the manually html for the hidden inputs and use @Html.HiddenFor(m => m.Request.TourId) etc so that the name attributes are consistent and will correctly bind.

Finally, I recommend you read What is ViewModel in MVC?. Using data models in your views, particularly when editing forms is poor practice.

Side note: You can use the following query in your POST methods to easily check the properties of your model that have validation errors

var errors = ModelState.Keys.Where(k => ModelState[k].Errors.Count > 0).Select(k => new
{
    propertyName = k,
    errorMessage = ModelState[k].Errors[0].ErrorMessage
});
Community
  • 1
  • 1
0

You shouldn't use the same name as the parameter as the model name, that will break the binding process on the way back. Try to change the signature from

public ActionResult Create(Request request)

to

public ActionResult Create(Request req)

To check for the ModelState errors use the following code:

foreach (ModelState modelState in ViewData.ModelState.Values)
{
 foreach (ModelError error in modelState.Errors)
 {
    var xx = error.ErrorMessage;
 }
}

If you put a breakpoint on var xx you will see what the error is but I'm pretty sure it's because there is no proper binding because of the names you used (In fact I will change the name Request for something else entirely but that's just me).

Hope this helps.

ProgrammerV5
  • 1,915
  • 2
  • 12
  • 22
  • thanks for your care but It's the same as the code which visual studio generate for controller to create Request model itself.but thanks i will try thank you. – neda Derakhshesh Jun 28 '16 at 11:46