1

I have a class in my project which looks like this:

public class MyClass
{
   [Required]
   public string keyword { get; set; }
   public string saleRange { get; set; }
}

This is how the action looks like:

[HttpPost]
    [ActionName("Analyze")]
    public ActionResult Analyze(MyClass obj)
    {
        if (!ModelState.IsValid)
        {
            return Json("error");
        }
        else
        {
            return Json("ok");
        }
    }

And in jQuery:

  $(document).on("click",".btnAnalyze",function() {
        var data =
        {
            keyword: $(".keywordInput").val(),
            saleRange: "1"
        };
        console.log($(".keywordInput").val());
        $.post("/Controller/Analyze",data).done(function(){
            if (data == "error") {
                alert("all fields are required");
            }
        });
    });

As you can see I'm mapping a JS object to a C# class object which I pass to my action. Now what the problem here is, even if I don't supply anything for the keyword property (ie. it's null or ""), the ModelState still shows it's property IsValid as true, but it should be set on false if I don't pass anything as keyword parameter.

This is first part of the problem, the other question I have here is how would I, If I have 10 textbox field, of which all are required. And if user enters only 1/10 of those, I would like to send a message for the first next field user has to validate in order to proceed, like "texbox #2 is required, please enter something" instead of a just general message like "all fields are required" or something like that ?

Can someone help me out with this ?

Why does the modelstate shows the it's valid even though after I dont' supply keyword parameter in the object?

@T.Jung here Is a sample of input:

 <input placeholder="Enter keywords" class="form-control keywordInput" type="text" style="width:80%">

It's basically just a plain input field in html..

4
  • 1
    Why are you doing your validation via an alert? Can't you just use the ModelErrors and the ValidaitionMessage from the HtmlHelper? Commented Jun 22, 2017 at 15:08
  • @T.Jung it's just a simple message so that I can know whether the validation passed or not ... Could you show me an example of those? I don't recall using them before Commented Jun 22, 2017 at 15:09
  • Can you add some coed of your view where you create one input field? Commented Jun 22, 2017 at 15:17
  • @T.Jung I added one , specifically the keyword field which I'm trying to perform a validation against, and that field is wrapped up in a form tag... Commented Jun 22, 2017 at 15:20

4 Answers 4

3

You can use form validation, which will perform data annotation validation on the client side and you do not have to go to the server side.

 $('#btnAnalyze').on('click', function (evt) {
    if ($('#YourformId').valid()) {
       //Perform AJAX call
    }

This way if any of the validations do not work, the form.valid() will throw the data annotation errors. So you can add Required to those fields in the models and it will ensure data is not sent if validation fails.

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

14 Comments

Does this returns information in regards to which fields aren't validated properly?
Yeah it should work the same way the data annotations work.
It says: Uncaught TypeError: $(...).valid is not a function
Okay I got it, I had to reference a few libs here n there... But the ModelState still shows it's validated (true) even after I pass the first parameter as null ?
Wait, if you have that if condition, It should not go to the AJAX call itself. Do you have <script src="/Scripts/jquery.unobtrusive-ajax.js"></script> <script src="/Scripts/jquery.validate.js"></script> <script src="/Scripts/jquery.validate.unobtrusive.js"></script> in your view?
|
3

I would do the following:

  1. Make sure your script bundle includes the following 2 files after your jquery and in this order:

    • jquery.validate.js
    • jquery.validate.unobtrusive.js
  2. Create your partial / view for your form:

@model MyClassObject

<form action="/action" method="post" id="form">
    <div class="row">
        @Html.ValidationMessageFor(m => m.Param1)
        @Html.LabelFor(m => m.Param1, new { @class = "label" })
        @Html.TextBoxFor(m => m.Param1, new { @class = "textbox" })
    </div>
    <div class="row">
        @Html.ValidationMessageFor(m => m.Param2)
        @Html.LabelFor(m => m.Param2, new { @class = "label" })
        @Html.TextBoxFor(m => m.Param2, new { @class = "textbox" })
    </div>
    <div class="row">
        @Html.ValidationMessageFor(m => m.Param3)
        @Html.LabelFor(m => m.Param3, new { @class = "label" })
        @Html.TextBoxFor(m => m.Param3, new { @class = "textbox" })
    </div>
    <input type="submit" value="submit">
</form>
  1. Do you server side validation
[HttpPost]
[ActionName("action")]
public ActionResult action(MyClassObject obj)
{
   if(!ModelState.IsValid)
   {
      return action(); // this is your original action before you do the post
   }
   else
   {
      // do your processing and return view or redirect
      return View(); // or redirect to a success page
   }
}
  1. Add the error message to your class:
public class MyClassObject
{
   [Required(ErrorMessage = "Please enter a keyword")]
   public string keyword { get; set; }
   public string saleRange { get; set; }
}
  1. Your js validation will be plumbed in now but you will need to stop the form from posting and check the validation before doing your ajax request:

var form = document.getElementById('form'), // get a normal js form (I do this just so I can pass in the method and action dynamically - seems better than using .attr() to get them
    jqForm = $(form);

jqForm.on('submit', function(e) {
  e.preventDefault();
  if (jqForm.valid()) {
    var formData = jqForm.serializeArray(); // I use serializeArray so I can add extra values if I need to, you can use serialize() 
    // formData.push({ name: this.name, value: this.value }); - optional for adding extra data 

    $.ajax({
      url: form.action,   // this can be just a specific json url if you just need to get some json - it doesn't have to be the same url as the fallback (no js url)
      type: form.method,
      data: formData,
      success: function(result) {
         // do success stuff!
      }
    });
  }
})

1 Comment

Pete yes good point, probably it's for the best that I use built in features of MVC rather than trying to find a workaround for something that works good , thanks ! :)
0

You should stringify the JavaScript Object in the Jquery post

JSON.stringify(data)

1 Comment

In this case then both parameters are nulll
0

If you want to do the Validation on server side:

Contoller:

[HttpPost]
[ActionName("Analyze")]
public ActionResult Analyze(Model viewModel)
{
    if(viewModel.PropertyName.IsNullOrEmpty()){
    {
        ModelState.AddModelError("PropertyName", "The Field InputFieldName neeeds to be filled!");
    }
    if (ModelState.IsValid)
    {
        //Do what ever you want with your Inofrmation
        //return a redirct or anything else
    }
    //If you got here some fields are not filled
    return View(viewModel);
}

View:

@Html.TextBoxFor(x => x.PropertyName)
@Html.ValidationMessageFor(m => m.PropertyName, "", new { @class = "text-danger" })
//@class = "text-danger" only if you're using bootstrap

I do all of my validation this way.

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.