为什么 form method=post 会重置一个数据实例?

Why is form method=post resetting a data instance?

我正在尝试将图像 url 字符串添加到数据库中的访问者徽章 属性。我有一个页面,我从数据库中调用访问者的实例,然后格式化来自访问者的一些信息,对其进行截图,并生成图像 url。 OnGetAsync 工作正常,但是,我无法在 OnPostAsync 期间将 url 到 post 发送到服务器。我已将问题缩小到表单标签,因为当我尝试使用表单标签方法 post 数据时 =post,访问者的实例丢失,因此 ModelState 无效(当删除表单标签时,会生成 url,所以我知道 BadgeDataUrl 不是空的)。

为什么访问者实例会重置?我一直在搜索其他 post,但没有看到任何人有类似的重置问题。我还尝试在 OnPostAsync 中再次设置访问者,但 ModelState 仍然无效,因为它将访问者的属性视为 null(这很奇怪,因为当我添加属性监视时,数据正确显示 - 我是不确定为什么 ModelState 无效)。

RegistrationSuccess.cshtml.cs

public async Task<IActionResult> OnGetAsync(string visitorId)
{
    if (visitorId == null)
    {
        return NotFound();
    }
    Visitor = await _context.Visitor.FirstOrDefaultAsync(m => m.ID.ToString() == visitorId);
    if (Visitor == null)
    {
        return NotFound();
    }
    return Page();
}

public async Task<IActionResult> OnPostAsync()
{
    if (!ModelState.IsValid)
    {
        return Page();
    }
    //Badge processing
    var base64Badge = BadgeDataUrl.Split(",")[1];
    var binaryBadge = Convert.FromBase64String(base64Badge);
    System.IO.File.WriteAllBytes("Badge.jpg", binaryBadge);
    Visitor.FutureBadge = BadgeDataUrl;
            
    _context.Attach(Visitor).State = EntityState.Modified;

    try
    {
        await _context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!VisitorExists(Visitor.ID))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    } 
    return RedirectToPage("/Visitors/RegistrationSuccess");
}
        
private bool VisitorExists(int id)
{
    return _context.Visitor.Any(e => e.ID == id);
}

RegistrationSuccess.cshtml
@page "{visitorId}"
@model VisitorManagementSystem.Pages.Visitors.RegistrationSuccessModel
@{
}
@{
    ViewData["Title"] = "Success";
}

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>HTML TO IMAGE</title>
    <script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
    <script type="text/javascript">
        function downloadimage() {
            var container = document.getElementById("htmltoimage");; // full page
            html2canvas(container, { allowTaint: true }).then(function (canvas) {
               var badgeData = canvas.toDataURL("image/jpeg");
                $('#BadgeDataUrl').val(badgeData);
            });
            }
    </script>
    <style>
        #htmltoimage {
            width: 65%;
            margin: auto;
        }
    </style>
</head>

<body>
    <form method="post">
        <br />
<div id="htmltoimage">
            <div id="badge" style=" box-sizing: border-box; background-color: white; border: 2px solid black; margin: 50px; padding: 0px; width: 10.15cm; height: 6.096cm">
                <div style="text-align:center; float:left; padding:0; float:left; vertical-align:top; background-color:red; color:white; font-family:Arial; font-size:25px; width:10.06cm">
                    <label>VISITOR</label>
                </div>
                <div style="float:left">
                    <img style="margin-left:18px; margin-top:13px; border:1px solid black; width: 3.2cm; height:2.4cm" src="@Model.Visitor.Picture" alt="Visitor Picture" />
                    <div style="text-align:left; margin-left:15px; margin-top:9px; line-height:0.8; font-size:13px; padding:5px;">
                        <label>CCI Host:</label><br>
                        <label id="destinationlabel">@Model.Visitor.Destination</label><br><br />
                    </div>
                </div>
                <div style="float:right; margin-top:3px; margin-right:7px; margin-bottom:0px; font-family: Arial; vertical-align:top">
                    <label id="datelabel">@Model.Visitor.DateCheckedIn.ToShortDateString()</label>
                </div>
                <div style="float:left; line-height:0.8; vertical-align:top">
                    <div style="font-size:45px; margin-top: 30px; line-height:0.1; margin-bottom:5px; margin-left:20px; margin-right:0; font-weight: bold;">@Model.Visitor.FirstName</div><br />
                    <div style="font-size:45px; margin-top: 5px; margin-bottom:10px; margin-left:20px; margin-right:0; font-weight: bold;">@Model.Visitor.LastName</div>
                    <label id="companynamelabel" style="font-size:18px; margin-left: 20px">@Model.Visitor.CompanyName</label><br>
                    <label id="titlelabel" style="font-size:18px; margin-left:20px">@Model.Visitor.CompanyTitle</label>
                </div>
                <div style="padding: 0px; margin: 0px; position: absolute; bottom: 0; left: 0; width: 10.05cm; background-color: red; color: white; font-family: Arial; font-size: 15px; text-align: right">
                    <label id="bottomredbar"></label>
                </div>
            </div>
        </div>
        <button type="submit" onclick="downloadimage()" class="clickbtn" id="downloadButton">Download/Print Badge</button><br />
        <div>
            @*This is here just to check if the url is generating*@
            <input asp-for="@Model.BadgeDataUrl">
        </div>
    </form>
</body>

我是新手,非常感谢您的帮助!



编辑
Registration.cshtml.cs 没有 ModelState 验证:

public class RegistrationSuccessModel : PageModel
{
    [BindProperty]
    public Visitor Visitor { get; set; }

    [BindProperty]
    public string BadgeDataUrl { get; set; }

    private readonly VisitorManagementSystem.Data.VisitorManagementSystemContext _context;

    public RegistrationSuccessModel(VisitorManagementSystem.Data.VisitorManagementSystemContext context)
    {
        _context = context;
    }
    public async Task<IActionResult> OnGetAsync(string visitorId)
    {
        if (!string.IsNullOrEmpty(visitorId))
        {
            Visitor = _context.Set<Visitor>().FirstOrDefault(i => i.ID.ToString() == visitorId);
        }
        return Page();
    }

    public async Task<IActionResult> OnPostAsync(string visitorId)
    {
        Visitor = _context.Set<Visitor>().FirstOrDefault(i => i.ID.ToString() == visitorId);
        var base64Badge = BadgeDataUrl.Split(",")[1];
        var binaryBadge = Convert.FromBase64String(base64Badge);
        System.IO.File.WriteAllBytes("Badge.jpg", binaryBadge);
        Visitor.FutureBadge = BadgeDataUrl;
            
        _context.Attach(Visitor).State = EntityState.Modified;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!VisitorExists(Visitor.ID))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToPage("/Visitors/RegistrationSuccess");
    } 
    private bool VisitorExists(int id)
    {
        return _context.Visitor.Any(e => e.ID == id);
    }
}
  1. Visitor 在 OnGet 方法中设置的值而不是全局值。所以你不能把它放在另一个请求中。此外,您使用 BindProperty 并且此属性用于在您的场景中绑定表单中的值。

  2. 但是你使用的标签元素不能绑定到后端。一种方法是你可以通过使用 jquery 和 post 来获取元素值 ajax (如果你想在 post 返回时做任何事情,这会有点复杂) .另一种方法是为每个 属性.

    设置隐藏输入
  3. 如果你使用type="submit"输入,它不会触发onclick事件。您需要更改为 type="button".

  4. html2canvas.js 的引用在我的项目中出错。所以我改为:

    <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.1.4/dist/html2canvas.min.js"></script>
    

这是一个完整的工作演示:

Registration.cshtml:

<head>
    <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.1.4/dist/html2canvas.min.js"></script>
    <script type="text/javascript">
        function downloadimage() {
            var container = document.getElementById("htmltoimage");; // full page
            html2canvas(container, { allowTaint: true }).then(function (canvas) {
                var badgeData = canvas.toDataURL("image/jpeg");
                $('#BadgeDataUrl').val(badgeData);
                $('form').submit();  //add this...
            });
        }
    </script>       
</head>
<body>
    <form method="post">   //add hidden input to make form data post successfully....
        <input asp-for="Visitor.Destination" hidden />
        <input asp-for="Visitor.DateCheckedIn" hidden />
        <input asp-for="Visitor.FirstName" hidden />
        <input asp-for="Visitor.LastName" hidden />
        <input asp-for="Visitor.CompanyName" hidden />
        <input asp-for="Visitor.CompanyTitle" hidden />
        <input asp-for="Visitor.Picture" hidden />
        <br />
        <div id="htmltoimage">
            <div id="badge" style=" box-sizing: border-box; background-color: white; border: 2px solid black; margin: 50px; padding: 0px; width: 10.15cm; height: 6.096cm">
                <div style="text-align:center; float:left; padding:0; float:left; vertical-align:top; background-color:red; color:white; font-family:Arial; font-size:25px; width:10.06cm">
                    <label>VISITOR</label>
                </div>
                <div style="float:left">
                    <img style="margin-left:18px; margin-top:13px; border:1px solid black; width: 3.2cm; height:2.4cm" src="@Model.Visitor.Picture" alt="Visitor Picture" />
                    <div style="text-align:left; margin-left:15px; margin-top:9px; line-height:0.8; font-size:13px; padding:5px;">
                        <label>CCI Host:</label><br>
                        <label id="destinationlabel">@Model.Visitor.Destination</label><br><br />   
                    </div>
                </div>
                <div style="float:right; margin-top:3px; margin-right:7px; margin-bottom:0px; font-family: Arial; vertical-align:top">
                    <label id="datelabel">@Model.Visitor.DateCheckedIn.ToShortDateString()</label>    
                </div>
                <div style="float:left; line-height:0.8; vertical-align:top">
                    <div style="font-size:45px; margin-top: 30px; line-height:0.1; margin-bottom:5px; margin-left:20px; margin-right:0; font-weight: bold;">@Model.Visitor.FirstName</div><br />
                    <div style="font-size:45px; margin-top: 5px; margin-bottom:10px; margin-left:20px; margin-right:0; font-weight: bold;">@Model.Visitor.LastName</div>
                    <label id="companynamelabel" style="font-size:18px; margin-left: 20px">@Model.Visitor.CompanyName</label><br>
                    <label id="titlelabel" style="font-size:18px; margin-left:20px">@Model.Visitor.CompanyTitle</label>  
                </div>
                <div style="padding: 0px; margin: 0px; position: absolute; bottom: 0; left: 0; width: 10.05cm; background-color: red; color: white; font-family: Arial; font-size: 15px; text-align: right">
                    <label id="bottomredbar"></label>
                </div>
            </div>
        </div>
                   //change here....
        <button type="button" onclick="downloadimage()" class="clickbtn" id="downloadButton">Download/Print Badge</button><br />
        <div>
            <input asp-for="@Model.BadgeDataUrl">
        </div>
    </form>
</body>