简体   繁体   中英

Improve nameof() in C#

I am using ASP.NET Core MVC with C#.

I define my model like this:

public class Student
{
      public class FirstName {get;set;}
      public int? PriorityId { get; set; }
}

public class Priority
{
    [Key]
    public int PriorityId { get; set; }
    [Required]
    [Display(Name = "Priority Name")]
    public string Name { get; set; }        
}

So it will render HTML for priority dropdown like this.

<div class="col-sm-4">
     <div class="form-group">
         <label for="Student_PriorityId">Priority<span style="color:red"> *</span></label>
         <select class="form-control valid" id="Student_PriorityId" name="Student.PriorityId" aria-invalid="false">
              <option selected="selected" value="0">Select</option>
              <option value="3">High</option>
              <option value="1">Low</option>
              <option value="2">Medium</option>
         </select>
         <span class="text-danger field-validation-error" data-valmsg-for="Student.PriorityId" data-valmsg-replace="true">Priority is required.</span>
     </div>
</div>

Problem

When I am going to check custom validation the message is not display below dropdown.

if (obj.Student.PriorityId <= 0)
{
    ModelState.AddModelError(nameof(obj.Student.PriorityId), "Priority is required.");
}

The above code is not working when I try using nameof() .

But when I remove nameof() and write down as string like below. It shows me error message below drop down successfully.

if (obj.Student.PriorityId <= 0)
{
    ModelState.AddModelError("Student.PriorityId", "Priority is required.");
}

Is there any way where I can improve nameof() function of C#?

I'm not sure this is an improvement but you could write a method like this:

public static string NameOf<T>(Expression<Func<T>> func)
{
    return string.Join(".", func.ToString().Split('.').Reverse().Take(3).Reverse().ToArray());
}

Then your code would be

if (obj.Student.PriorityId <= 0)
{
    ModelState.AddModelError(NameOf( () => obj.Student.PriorityId ), "Priority is required.");
}

In this case, NameOf would return "obj.Student.PriorityId".

Here is an example of how to use CallerArgumentExpressionAttribute as a replacement for nameof .

using Microsoft.AspNetCore.Mvc.ModelBinding;
using System.Runtime.CompilerServices;
public static class ModelStateExtensions
{
    public static void AddModelErrorEx(
        this ModelStateDictionary modelStateDictionary,
        object _,
        string errorMessage,
        [CallerArgumentExpression("_")] string expr = "")
        => modelStateDictionary.AddModelError(expr, errorMessage);
}

Usage:

// Argument 'expr' will be "Student.PriorityId" here.
ModelState.AddModelErrorEx(Student.PriorityId, "Priority is required.")

// Argument 'expr' will be "obj.Student.PriorityId" here.
ModelState.AddModelErrorEx(obj.Student.PriorityId, "Priority is required.")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM