I like to use nameof() in my ASP.NET Core application when setting mvc errors using ModelState.AddModelError(). This reduces hidden errors since I pass the name of an attribute here. Compared to a string, this has the benefit that a compiler error is thrown when the attribute was renamed.
Example
class MyModel{
public string Name{get;set;}
}
public class MyController:Controller{
public IActionResult Test(MyModel model) {
// Will hiddenly fail when "Name" is renamed to something else
ModelState.AddModelError("Name", "The Name field is required!");
// Better: Using the auto renaming feature of VS, this will be updated if "Name" was renamed
ModelState.AddModelError(nameof(model.Name), "The Name field is required!");
}
}
This works, until I have another entity:
class MyModel{
public string Name{get;set;}
public MyOtherModel OtherModel{get;set;}
}
class MyOtherModel{
public string OtherName{get;set;}
}
Now I want to get the name of OtherModel
. The problem: ASP.NET requires BaseClass.ChildClass pattern here, so OtherModel.OtherName
in this example. Using the same logic like above:
public class MyController:Controller{
public IActionResult Test(MyModel model) {
ModelState.AddModelError(nameof(model.MyOtherModel.OtherName), "The Name field is required!");
}
}
will just give me the name of the child attribute, so OtherName
in this example. But I need OtherModel.OtherName
. Is there a clean way to get this without building the string itself?
This would be possible doing something like this:
string actionName = nameof(model.MyOtherModel) + "." + nameof(model.MyOtherModel.OtherName);
But not a very clean and intuitive way imho.
As others have suggested, you will probably have to write your own method to do this. This is what I came up with using Linq.Expressions:
You would then use it like this:
NameOfMember(model => model.MyOtherModel.OtherName)
I'm not familiar with ASP.NET but you can change Model to any type you want, including object.
As a side note, you shouldn't repeat "The Name field is required!" in your code. Maybe you can include that in your helper method as well.