0

I have a simple model like:

public class Employer 
{
    [Required(ErrorMessage = "Please specify id")]
    public int Id { get; set; }

    [MaxLength(256, ErrorMessage = "Max lenght should be less than 256")]
    [Required(ErrorMessage = "Please specify Name")]
    public string Name { get; set; }

    [Required(ErrorMessage = "Please specify id of organization")]
    public int OrganizationId { get; set; }
}

then controller is:

public IHttpActionResult Post(Employer employer)
{
    if(!IsActiveOrganization(employer.OrganizationId))
    {
        ModelState.AddModelError(nameof(employer.OrganizationId), "The organization is not active!");
    }
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }
}

As you can see I'm trying to validate model before creating a new employer. So, when I pass model with invalid id then response will like:

{
  "message": "The request is invalid.",
  "modelState": {
    "employer.Id": [
      "Please specify id."
    ]
  }
}

I want to check if OrganizationId is active. For that I have a method IsActiveOrganization it checks and returns true/false. If false then I need to add model error and return 400 Bad Request to client. Everything works but in way that I implemented I will get response like:

{
  "message": "The request is invalid.",
  "modelState": {
    "employer.Id": [
      "Please specify id"
    ],
    "OrganizationId": [
      "The organization is not active!"
    ]
  }
}

How can I add prefix to ModelState error key like employer.Id for my own error OrganizationId? Should I have hardcode employer.OrganizationId or there is any better way? Please let me know if I need to add mode details. Thanks.

Robert N. Dean
  • 1,219
  • 1
  • 14
  • 27

3 Answers3

4

While nameof is great for avoiding hardcoding property names, it's not without it's flaws, and you've stumbled upon one of the major ones: it only returns the name of the referenced property, not the full object graph you used to access it. If you want to avoid hardcoding then, you'll have to do something like:

ModelState.AddModelError($"{nameof(employer)}.{nameof(employer.OrganizationId)}", "Error message here");

It's not exactly pretty, but it's the best you can do.

Chris Pratt
  • 232,153
  • 36
  • 385
  • 444
  • It is almost the same `ModelState.AddModelError("employer.OrganizationId", "Error message here");` I know that property can be renamed but not in this case – Robert N. Dean Jun 01 '17 at 20:08
  • Well, not quite. Using `nameof` for both, you'd still be covered if either the name of `employer` or `OrganizationId` were to change, but you are still sort of hardcoding the connection between the two. There's just no way around that, though. – Chris Pratt Jun 02 '17 at 12:52
0

try to use remote validation

    [Remote("Action", "controller" ErrorMessage = "ErrorMsg")]
    [Required(ErrorMessage = "Please specify id of organization")]
    public int OrganizationId { get; set; }

In your Action look like this

public JsonResult Post(int OrganizationId )
{
    if(!IsActiveOrganization(OrganizationId ))
    {
        return Json(false, JsonRequestBehavior.AllowGet);
    }
    if (!ModelState.IsValid)
    {
        return Json(false, JsonRequestBehavior.AllowGet);
    }
}
Jay
  • 703
  • 9
  • 21
0

You can create your own data attribute for this, if you want some custom names, but you don't really need this, you can write what ever name you want as AddModelError, takes 2 strings, (string key, string Message) so i don't think it really makes a difference

Munzer
  • 2,216
  • 2
  • 18
  • 25