3

I'm new to ASP.Net WebApi. Apologies therefore if this has been asked before (I'm unsure of the correct terminology), but I can only find this related answer which is slightly different to my problem.

I need to create a Post controller that accepts a complex type (a TestObject), containing:

  1. An IEnumerable<Person>, where Person has properties Username and ExternalId
  2. Options on how the controller should handle the data (a TestOptions object)

I have defined the classes below with data annotations to assist with validation:

public class TestObject
{
    public IEnumerable<TestPerson> TestPerson;
    public TestOptions Options;

    public void TestOject()
    {
        this.TestPerson = new List<TestPerson>();
        this.Options = new TestOptions();
    }
}

public class TestPerson
{
    [Required, MaxLength(50)]
    public string ExternalId;

    [Required, MaxLength(50)]
    public string Username;
}

public class TestOptions
{
    [Required]
    public bool Option1;

    [Required, MaxLength(50)]
    public string Option2;
}

The controller accepts TestObject and performs validation before doing anything:

    [Route("test")]
    public HttpResponseMessage Post([FromBody] TestObject t)
    {
        if (!ModelState.IsValid)
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
        }
        else
        {
            return Request.CreateResponse(HttpStatusCode.OK, string.Format("Found {0} people", t.TestPerson.Count().ToString()));
        }
    }

If I use Fiddler to send a sample JSON object the with correct structures, it works fine. However, if I deliberately introduce errors (E.g. Username and Option2 missing) like this...

{
   "TestPerson":[
      { "ExternalId":"123", "Username":"Bob" },
      { "ExternalId":"123" }
   ],
   "Options":{"Option1":false}
}

I still get

Status 200

2 people found

Why is this happening please? Can I use data annotation validation on complex types?

Update

Debugging image with property values being set:

enter image description here

Community
  • 1
  • 1
EvilDr
  • 8,943
  • 14
  • 73
  • 133

2 Answers2

3

Instead of using fields you need to convert them to properties for this to work:

[Required, MaxLength(50)]
public string ExternalId { get; set; }

[Required, MaxLength(50)]
public string Username { get; set; }

Do this for all of your public fields.

Did you look at the object using the debugger and see if the fields were being set? They probably were, but see here for some detail on modelbinding:

ASP.net MVC - Model binding excludes class fields

Update:

I have tried and tested this and am sure it will fix your issue.

Community
  • 1
  • 1
Ric
  • 12,855
  • 3
  • 30
  • 36
  • Thanks. I added getters and setters but the validation is *still* not occurring. I've attached an image of the debugger showing values being set. Perhaps you can spot something missing? – EvilDr Jan 14 '16 at 14:00
  • 1
    Yes, you didnt set the fields in `TestObject` to properties! – Ric Jan 14 '16 at 14:04
  • Arrgh; face-palm moment... Thank you - it's working. Just out of interest, do you know why this validation doesn't work on fields, and only properties. The other question states it's by design, but is there a reason for that? – EvilDr Jan 14 '16 at 14:08
  • 1
    I've no idea why. Looked into it a bit but just accepted that this is the way it is! – Ric Jan 14 '16 at 14:12
  • Excellent. Thanks anyway. – EvilDr Jan 14 '16 at 14:20
0

If you're not using TestPerson View that validator won't execute. Use

if(ModelState.IsValid && TryValidateModel(model.TestPerson, "TestPerson."))
{
   //Submodel will be validated here.
}
Kevin
  • 13
  • 3