有人可以帮助我理解为什么页面远程验证会阻止 asp 处理程序触发吗?

发布于 2025-01-09 03:04:15 字数 7361 浏览 1 评论 0原文

我在这里面临一个奇怪的问题。

我有一个页面,我在其中设置了 PageRemote 属性来验证字段,在同一页面上,我有 2 个按钮,每个按钮使用 asp-page-handler 属性调用不同的处理程序(1 个用于更新内容,另一个用于更新内容)删除它)。

如果我删除 PageRemote 验证,两个按钮的处理程序都会按预期触发,但是当我在页面上保留 PageRemote 验证时,不会调用按钮特定的处理程序,尽管 PageRemote 处理程序已正确触发。

此外,当在页面上保留 PageRemote 验证时,如果我强制其验证返回 false,则随后按钮会触发其各自的处理程序,但如果我不强制它,则行为如前所述,其中处理程序不是触发。

有人可以解释一下在同一页面上使用这两个东西是否有问题,和/或如何克服这个问题?

以下是页面代码的示例:

public class EditModel : PageModel
{
    
    private IConfiguration _configuration;

    [Required(ErrorMessageResourceType = typeof(ErrorMessages),
        ErrorMessageResourceName = nameof(ErrorMessages.SlugRequired))]
    [MinLength(3, ErrorMessageResourceType = typeof(ErrorMessages),
        ErrorMessageResourceName = nameof(ErrorMessages.SlugMinLength))]
    [MaxLength(128, ErrorMessageResourceType = typeof(ErrorMessages),
        ErrorMessageResourceName = nameof(ErrorMessages.SlugMaxLength))]
    [RegularExpression(@"^[0-9a-zA-Z_/-]*$", ErrorMessageResourceType = typeof(ErrorMessages),
        ErrorMessageResourceName = nameof(ErrorMessages.SlugAllowedCharacters))]
    [PageRemote(ErrorMessageResourceType = typeof(ErrorMessages),
        ErrorMessageResourceName = nameof(ErrorMessages.SlugDuplicate),
        AdditionalFields = "__RequestVerificationToken,GenericContentDTO.GenericContent.GenericContentId",
        HttpMethod = "post",
        PageHandler = "CheckSlug")]
    [Display(Name = "URL Title")]
    [BindProperty]
    public string Slug { get; set; }

    [TempData]
    public string FormResultMessage { get; set; }

    [BindProperty]
    public GenericContentDTO GenericContentDTO { get; set; }

    public EditModel(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public IActionResult OnGet(Guid genericContentId)
    {
        if (genericContentId.ToString() == "")
        {
            return NotFound();
        }

        ...
        Code to load content
        ...

        return Page();

    }

    public async Task<IActionResult> OnPostUpdate()
    {

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

        ...
        Code to update content
        ...

        return RedirectToPage(new { GenericContentId = GenericContentDTO.GenericContent.GenericContentId });

    }

    public IActionResult OnPostDelete()
    {

        ...
        Code to delete content
        

    }

    public JsonResult OnPostCheckSlug()
    {

        var token = HttpContext.Session.GetString("APIAuthorizationToken");

        CheckSlugDTO CheckSlug = new CheckSlugDTO
        {
            Slug = Slug,
            ContentId = GenericContentDTO.GenericContent.GenericContentId,
            Exists = true
        };

        CheckSlug = APICommunicationHelper.PostData<CheckSlugDTO>(CheckSlug, _configuration["AppConfigs:APIAddress"] + "api/CheckGenericContentSlugExistance", token);

        return new JsonResult(!CheckSlug.Exists);
    }
}

以及 Razor 代码的示例:

@page "{GenericContentId:Guid}"
@model MyProject.Pages.Generic_Contents.EditModel
@{
}

<form method="post" id="editForm" name="editForm" enctype="multipart/form-data">

<h3>@TempData["FormResultMessage"]</h3>

<ul class="nav nav-tabs">
    <li class="nav-item"><a class="nav-link active" data-toggle="tab" href="#main">Main</a></li>
    <li class="nav-item"><a class="nav-link" data-toggle="tab" href="#meta">Meta</a></li>
</ul>

<div class="tab-content">

    <div id="main" class="tab-pane active">
        <br />

        <div asp-validation-summary="ModelOnly" class="text-danger"></div>

        @Html.HiddenFor(model => model.GenericContentDTO.GenericContent.GenericContentId)

        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.Title" class="control-label"></label>
            <input asp-for="GenericContentDTO.GenericContent.Title" class="form-control" />
            <span asp-validation-for="GenericContentDTO.GenericContent.Title" class="text-danger"></span>
        </div>

        <div class="form-group">
            <label asp-for="Slug" class="control-label"></label>
            <input asp-for="Slug" class="form-control" />
            <span asp-validation-for="Slug" class="text-danger"></span>
        </div>

        <div class="form-group row">

            <div class="col-4">
                <label asp-for="GenericContentDTO.MainImage" class="control-label"></label>
                <input asp-for="GenericContentDTO.MainImage" type="file" class="form-control" />
            </div>

        </div>

        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.Summary" class="control-label"></label>
            @Html.TextAreaFor(model => model.GenericContentDTO.GenericContent.Summary, new { @class = "form-control", @rows = 5 })
            <span asp-validation-for="GenericContentDTO.GenericContent.Summary" class="text-danger"></span>
        </div>

        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.ContentText" class="control-label"></label>
            @Html.TextAreaFor(model => model.GenericContentDTO.GenericContent.ContentText, new { @class = "form-control editorHtml" })
        </div>

        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.IsActive" class="control-label"></label>
            @Html.CheckBoxFor(model => model.GenericContentDTO.GenericContent.IsActive)
        </div>

    </div>

    <div id="meta" class="tab-pane fade">
        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.MetaDescription" class="control-label"></label>
            @Html.TextAreaFor(model => model.GenericContentDTO.GenericContent.MetaDescription, new { @class = "form-control", @rows = 5 })
            <span asp-validation-for="GenericContentDTO.GenericContent.MetaDescription" class="text-danger"></span>
        </div>

        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.MetaKeywords" class="control-label"></label>
            @Html.TextAreaFor(model => model.GenericContentDTO.GenericContent.MetaKeywords, new { @class = "form-control", @rows = 5 })
            <span asp-validation-for="GenericContentDTO.GenericContent.MetaKeywords" class="text-danger"></span>
        </div>
    </div>


    <div class="form-group text-right">
        <a asp-area="" asp-page="/Generic-Contents" class="btn btn-secondary">Cancel</a>
        <button type="submit" class="btn btn-danger" asp-page-handler="Delete">Delete Content</button>
        <button type="submit" class="btn btn-primary" asp-page-handler="Update">Update Content</button>
    </div>

</div>

</form>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}    
}

谢谢

I'm facing an odd issue here.

I have a page where i have setup a PageRemote attribute to validate a field, and on the same page, i have 2 buttons that each call a distinct handler using the asp-page-handler property (1 to update the content, the other to delete it).

If i remove the PageRemote validation, the handlers for both buttons are triggered as expected, but when i leave the PageRemote validation on the page, the buttons specific handlers are not called, although the PageRemote handler is correctly triggered.

Furthermore, when leaving the PageRemote validation on the page, if i force its validation to return false, then afterwards the buttons trigger their respective handler, but if i do not force it, then the behaviour is as described earlier, where the handlers are not triggered.

Can someone explain me if there is a catch on using these two things on the same page, and/or how to overcome this?

Below is a sample of the page code:

public class EditModel : PageModel
{
    
    private IConfiguration _configuration;

    [Required(ErrorMessageResourceType = typeof(ErrorMessages),
        ErrorMessageResourceName = nameof(ErrorMessages.SlugRequired))]
    [MinLength(3, ErrorMessageResourceType = typeof(ErrorMessages),
        ErrorMessageResourceName = nameof(ErrorMessages.SlugMinLength))]
    [MaxLength(128, ErrorMessageResourceType = typeof(ErrorMessages),
        ErrorMessageResourceName = nameof(ErrorMessages.SlugMaxLength))]
    [RegularExpression(@"^[0-9a-zA-Z_/-]*
quot;, ErrorMessageResourceType = typeof(ErrorMessages),
        ErrorMessageResourceName = nameof(ErrorMessages.SlugAllowedCharacters))]
    [PageRemote(ErrorMessageResourceType = typeof(ErrorMessages),
        ErrorMessageResourceName = nameof(ErrorMessages.SlugDuplicate),
        AdditionalFields = "__RequestVerificationToken,GenericContentDTO.GenericContent.GenericContentId",
        HttpMethod = "post",
        PageHandler = "CheckSlug")]
    [Display(Name = "URL Title")]
    [BindProperty]
    public string Slug { get; set; }

    [TempData]
    public string FormResultMessage { get; set; }

    [BindProperty]
    public GenericContentDTO GenericContentDTO { get; set; }

    public EditModel(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public IActionResult OnGet(Guid genericContentId)
    {
        if (genericContentId.ToString() == "")
        {
            return NotFound();
        }

        ...
        Code to load content
        ...

        return Page();

    }

    public async Task<IActionResult> OnPostUpdate()
    {

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

        ...
        Code to update content
        ...

        return RedirectToPage(new { GenericContentId = GenericContentDTO.GenericContent.GenericContentId });

    }

    public IActionResult OnPostDelete()
    {

        ...
        Code to delete content
        

    }

    public JsonResult OnPostCheckSlug()
    {

        var token = HttpContext.Session.GetString("APIAuthorizationToken");

        CheckSlugDTO CheckSlug = new CheckSlugDTO
        {
            Slug = Slug,
            ContentId = GenericContentDTO.GenericContent.GenericContentId,
            Exists = true
        };

        CheckSlug = APICommunicationHelper.PostData<CheckSlugDTO>(CheckSlug, _configuration["AppConfigs:APIAddress"] + "api/CheckGenericContentSlugExistance", token);

        return new JsonResult(!CheckSlug.Exists);
    }
}

And of the Razor Code:

@page "{GenericContentId:Guid}"
@model MyProject.Pages.Generic_Contents.EditModel
@{
}

<form method="post" id="editForm" name="editForm" enctype="multipart/form-data">

<h3>@TempData["FormResultMessage"]</h3>

<ul class="nav nav-tabs">
    <li class="nav-item"><a class="nav-link active" data-toggle="tab" href="#main">Main</a></li>
    <li class="nav-item"><a class="nav-link" data-toggle="tab" href="#meta">Meta</a></li>
</ul>

<div class="tab-content">

    <div id="main" class="tab-pane active">
        <br />

        <div asp-validation-summary="ModelOnly" class="text-danger"></div>

        @Html.HiddenFor(model => model.GenericContentDTO.GenericContent.GenericContentId)

        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.Title" class="control-label"></label>
            <input asp-for="GenericContentDTO.GenericContent.Title" class="form-control" />
            <span asp-validation-for="GenericContentDTO.GenericContent.Title" class="text-danger"></span>
        </div>

        <div class="form-group">
            <label asp-for="Slug" class="control-label"></label>
            <input asp-for="Slug" class="form-control" />
            <span asp-validation-for="Slug" class="text-danger"></span>
        </div>

        <div class="form-group row">

            <div class="col-4">
                <label asp-for="GenericContentDTO.MainImage" class="control-label"></label>
                <input asp-for="GenericContentDTO.MainImage" type="file" class="form-control" />
            </div>

        </div>

        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.Summary" class="control-label"></label>
            @Html.TextAreaFor(model => model.GenericContentDTO.GenericContent.Summary, new { @class = "form-control", @rows = 5 })
            <span asp-validation-for="GenericContentDTO.GenericContent.Summary" class="text-danger"></span>
        </div>

        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.ContentText" class="control-label"></label>
            @Html.TextAreaFor(model => model.GenericContentDTO.GenericContent.ContentText, new { @class = "form-control editorHtml" })
        </div>

        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.IsActive" class="control-label"></label>
            @Html.CheckBoxFor(model => model.GenericContentDTO.GenericContent.IsActive)
        </div>

    </div>

    <div id="meta" class="tab-pane fade">
        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.MetaDescription" class="control-label"></label>
            @Html.TextAreaFor(model => model.GenericContentDTO.GenericContent.MetaDescription, new { @class = "form-control", @rows = 5 })
            <span asp-validation-for="GenericContentDTO.GenericContent.MetaDescription" class="text-danger"></span>
        </div>

        <div class="form-group">
            <label asp-for="GenericContentDTO.GenericContent.MetaKeywords" class="control-label"></label>
            @Html.TextAreaFor(model => model.GenericContentDTO.GenericContent.MetaKeywords, new { @class = "form-control", @rows = 5 })
            <span asp-validation-for="GenericContentDTO.GenericContent.MetaKeywords" class="text-danger"></span>
        </div>
    </div>


    <div class="form-group text-right">
        <a asp-area="" asp-page="/Generic-Contents" class="btn btn-secondary">Cancel</a>
        <button type="submit" class="btn btn-danger" asp-page-handler="Delete">Delete Content</button>
        <button type="submit" class="btn btn-primary" asp-page-handler="Update">Update Content</button>
    </div>

</div>

</form>

@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}    
}

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文