steventnorris
steventnorris

Reputation: 5896

Revalidate Model in Web API

I have model with fields below:

-Id : Required (database generated)
-Title : Required
-Status : Required
-Comments

When I run a post given this:

{
"title":"WOHOO",
"status":"STATUS"
}

Everything runs fine. However, when I run a post with the below:

{
"title":"WOHOO"
}

I get a model state issue because status is required. However, in my post method it is like this:

[Route(""), ResponseType(typeof(MyModel))]
public IHttpActionResult PostMyModel(MyModel model)
{
    // Save request in DB
    model.status = "Waiting";

    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    db.MyModels.Add(model);

    try
    {
        db.SaveChanges();
    }
    catch (DbUpdateException)
    {
        if (ModelExists(model.id))
        {
            return Conflict();
        }
        else
        {
            throw;
        }
    }

    return CreatedAtRoute("DisplayMyModel", new { id = model.id }, model);
}

I am setting the status at the start of this method, but the ModelState is as-is when the request starts. I can clear the ModelState with ModelState.Clear(), but then how do I revalidate the new model?

This is in an ApiController.

Upvotes: 1

Views: 1589

Answers (2)

Yishai Galatzer
Yishai Galatzer

Reputation: 8862

One alternative (correct for security, but more tedious)

Use separate objects for model binding and database access.

In this it is pretty simple, but you might get into cases where overbinding is an issue, so from security perspective, you want a separate DTO to bind to, check the validation, and then add your updates and pass to the database.

See this Link for more reading.

Alternatively

In your case, you can just remove the single error you are encountering (because it is well known) and then check ModelState.IsValid.

ModelState.Remove("status");

if (!ModelState.IsValid)
{
    ...
}

for deeply nested object you will save some significant processing for validation.

Upvotes: 0

steventnorris
steventnorris

Reputation: 5896

The correct way to approach this is to first clear the model state, then call the Validate method with the new model. This adds any validation errors to the model state. See below:

ModelState.Clear();
model.status = "Waiting";
Validate<MyModel>(model);

if(!ModelState.IsValid){

etc...

Upvotes: 8

Related Questions