Asp.Net 核心 Razor 页面中的远程验证

Remote Validation in Asp.Net Core Razor Pages

我正在使用 Razor Pages 和 Code First 开发 Web 应用程序。

我知道在 ASP.NET MVC 中,您可以在 属性 上方使用 Remote 来指代控制器中验证数据而不回发整个页面的操作。但它似乎在 Razor Pages 中不起作用,因为 ASP.NET Core Razor Pages 中没有控制器和操作。

那么,如何在 Razor Pages 中完成远程验证?

ASP.NET Core Razor Pages 中似乎有远程验证的功能请求,但它不是优先级:

https://github.com/aspnet/Mvc/issues/8245

我在我的模型中添加了以下内容class:

 [Remote(action: "IsNationalIdValid",controller:"Validations")]

我在我的 Razor Pages 项目中创建了 'Controllers' 文件夹,并使用以下方法添加了一个控制器 (ValidationsController):

        public IActionResult IsNationalIdValid(string nationalId){}

但是,当我尝试转到本应进行此验证的页面时,出现以下异常:

No URL for remote validation could be found in asp.net core

感谢 Asp.Net 论坛中对同一主题的回复,我找到了答案: 我需要做的就是在我的 Razor Pages 项目的 Startup.cs 文件中添加以下代码以配置路由。

app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });

希望这个回答对其他人也有帮助。

RemoteAttribute 派生的基础 class 中,有一个受保护的 GetUrl() 方法可以被覆盖。因此我创建了自己的 MyRemoteAttribute class

public class MyRemoteAttribute : RemoteAttribute
{
    /// <summary>
    /// Initialise an instance of the <see cref="MyRemoteAttribute"/>
    /// </summary>
    /// <param name="handler">The name of the Razor Page Handler</param>
    /// <param name="page">The Razor Page name</param>
    public MyRemoteAttribute(string handler = null, string page = null)
    {
        Handler = handler;
        Page = page;
    }

    /// <summary>
    /// Gets/sets the url to use for remote validation
    /// </summary>
    public string Url { get; set; }
    public string Page { get; private set; }
    public string Handler { get; private set; }

    protected override string GetUrl(ClientModelValidationContext context)
    {
        // Use an URL is specified
        if (!string.IsNullOrEmpty(Url)) return Url;

        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }
        if (string.IsNullOrEmpty(Handler))
        {
            throw new InvalidOperationException("No Handler specified");
        }

        var services = context.ActionContext.HttpContext.RequestServices;
        var factory = services.GetRequiredService<Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory>();
        var urlHelper = factory.GetUrlHelper(context.ActionContext);

        var page = Page?? context.ActionContext.RouteData.Values["page"] as string;

        Url = urlHelper.Page(page, Handler);
        if (Url == null)
        {
            throw new InvalidOperationException();
        }

        return Url;
    }
}

在我使用区域的应用程序中,创建一个 url /BusinessPartners/Clients/Create?handler=CheckUnique

使用 属性 修饰模型 [MyRemote(Url="/Something/Somecheck")] 以使用指定的 URL,或 [MyRemote("CheckUnique")] 指定 Razor 页面处理程序。处理程序应命名为 OnGet<handlername> 并且需要 return 一个 JsonResulttrue 以通过验证,如果验证失败则 falsenull

Razor 页面中的处理程序是:

public IActionResult OnGetCheckUnique(string shortName)
{
    var found = db.Queryable<BusinessPartner>().Any(a => a.ShortName == shortName);
    return new JsonResult(!found);
}

这与您为 RemoteAttribute 所做的相同,只是命名约定略有修改。

我希望我的验证接近使用它的地方,因此我将它放在同一页面中。我也为模型 class 使用了一个 [BindProperty] 只是为了保持整洁和易于管理。

对于像我这样后来发现这个并且失去理智试图将 属性 从他们的模型传递到验证方法的人,让方法签名看起来像这样

public IActionResult IsCharacterNameAvailable([Bind(Prefix = "Character.Name")] string name)

人物是模特,名字是属性。如果不在参数前添加 [Bind(Prefix = "")],我总是收到一个空值。希望这可以帮助!

PageRemoteValidation 属性是在 ASP.NET Core 3.0 中引入的,专门设计用于与 Razor Pages 处理程序方法一起使用。

因此,如果您使用 ASP.NET 核心 2.x,或者您的验证端点是 MVC 控制器,则必须使用 RemoteValidation 属性。如果您使用 ASP.NET Core 3.x 或更新版本,并且您的验证服务是 Razor Pages 处理程序方法,则必须使用 PageRemoteValidation 属性。

Here 是一个详细描述的示例: