Issue
I'm trying to add an image URL string to a visitor's Badge property in a database. I have a page where I'm calling an instance of a visitor from a database and then formatting some info from the visitor, screenshotting it, and generating an image URL. OnGetAsync works fine, however, I cannot get the URL to post to the server during OnPostAsync. I've narrowed the issue down to just the form tag, since when I try to post the data using the form tag method=post, the instance of the visitor is lost, so ModelState is invalid (when form tag is removed, the URL is generated, so I know it's not that BadgeDataUrl is null).
Why is the visitor instance resetting? I've been searching through other posts, but I'm not seeing anyone with a similar reset problem. I've also tried setting the visitor again in OnPostAsync, but ModelState is still invalid because it sees the properties of the visitor as null (which is strange because when I add a watch for the properties, the data shows up correctly--I'm not sure why ModelState is invalid then).
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 without ModelState validation:
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);
}
}
Solution
Visitor
value set in OnGet method instead of global. So you could not keep it in another request. Besides, you useBindProperty
and this attribute is used to bind the value from form in your scenario.But you use label element which cannot be bound to backend. One way is that you can get elements value by using jquery and post them by ajax(This will be a bit complex if you want to do anything when post back). The other way is to set hidden input for each property.
If you using
type="submit"
input, it will not hit onclick event. You need change totype="button"
.The reference for
html2canvas.js
makes an error in my project. So I change to:<script src="https://cdn.jsdelivr.net/npm/html2canvas@1.1.4/dist/html2canvas.min.js"></script>
Here is a whole working demo:
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>
Answered By - Rena
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.