SignalR Update Panel Only Works First Time - updatepanel

I have the following code inside of an update panel. When the screen loads, the SignalR code works fine. However, after the first time, once I click a button, the SignalR code does not fire anymore until I cause a redirect back to the page.
Basically what I am doing is when the user clicks the preview button, it fires off the reporting process. An Ajax modal popup is displayed with a progress indicator and a cancel button. If the user clicks the cancel button, the cancelation token is set, and the report is canceled. By using the SignalR technology, the ui thread is not blocked and the user can click the cancel button. This works fine the first time in. however, after clicking the cancel button, the next time when you click on the cancel button it does not work. However, when I redirect to the page again it works.
If I move the linkbutton outside of the update panel it works every time.
<asp:updatepanel runat="server" id="UpdatePanelFooter" rendermode="Inline" updatemode="Conditional">
<contenttemplate>
<table width="100%">
<tr>
<td>
<div id="divBottomBanner">
<asp:label id="LabelHelpID" runat="server" text="" visible="false"></asp:label>
<asp:linkbutton id="LinkButtonPreview" runat="server" OnClick="LinkButtonPreview_Click">Preview</asp:linkbutton>
<asp:linkbutton id="LinkButtonSaveAs" runat="server" onclick="LinkButtonSaveAs_Click">Save Prompts As</asp:linkbutton>
<asp:linkbutton id="LinkButtonGenerateSP" runat="server" onclick="LinkButtonGenerateSP_Click"><<<< GENERATE SP >>>></asp:linkbutton>
<asp:linkbutton id="LinkButtonInvisibleTargetControlIDSAVEAS" runat="server" causesvalidation="false" height="0" text="" width="0"></asp:linkbutton>
<asp:linkbutton id="LinkButtonInvisibleTargetControlIDPROGRESS" runat="server" causesvalidation="false" height="0" text="" width="0"></asp:linkbutton>
</div>
</td>
</tr>
</table>
<ajaxtoolkit:modalpopupextender id="ModalPopupExtenderPROGRESS" runat="server" targetcontrolid="LinkButtonInvisibleTargetControlIDPROGRESS" behaviorid="PROGRESS" popupcontrolid="PanelPROGRESS" backgroundcssclass="ModalBackground" dropshadow="true">
</ajaxtoolkit:modalpopupextender>
<asp:panel id="PanelPROGRESS" runat="server" cssclass="ModalPopup" style="display: none;" width="75em">
<table id="TablePROGRESS" width="95%">
<tr>
<td style="width: 10%"></td>
<td style="width: 30%"></td>
<td style="width: 50%"></td>
<td style="width: 10%"></td>
</tr>
<tr>
<td></td>
<td colspan="2" align="center">Processing Please Wait
<br />
<br />
<hr />
</td>
</tr>
<tr>
<td></td>
<td colspan="2" align="center">
<img src="../Images/moving_lights.gif" alt="Processing..." />
<hr />
</td>
</tr>
<tr>
<td>
<br />
<br />
</td>
</tr>
<tr>
<td></td>
<td align="center" colspan="2">
<asp:linkbutton id="LinkButtonCancelPROGRESSXD" runat="server" height="100%" cssclass="Button" causesvalidation="false" tabindex="6"> Cancel Preview Report </asp:linkbutton>
</td>
</tr>
<tr>
<td>
<br />
<br />
</td>
</tr>
</table>
</asp:panel>
</contenttemplate>
</asp:updatepanel>
I then have the following code in the script that is used in the SignalR section.
/// <reference path="../scripts/jquery-1.8.3.js" />
/// <reference path="../scripts/jquery.signalR-1.0.0.js" />
/*!
ASP.NET SignalR Report Processing
*/
// Crockford's supplant method
if (!String.prototype.supplant) {
String.prototype.supplant = function (o) {
return this.replace(/{([^{}]*)}/g,
function (a, b) {
var r = o[b];
return typeof r === 'string' || typeof r === 'number' ? r : a;
}
);
};
}
// A simple background color flash effect that uses jQuery Color plugin
jQuery.fn.flash = function (color, duration) {
var current = this.css('backgroundColor');
this.animate({ backgroundColor: 'rgb(' + color + ')' }, duration / 2)
.animate({ backgroundColor: current }, duration / 2);
}
$(function () {
var RPT = $.connection.ReportProcessing;
function stopRPT() {
//$ReportProcessingUl.stop();
}
function init() {
return RPT.server.waitForReportToBeReady().done(function () {
// Add Code Here
});
}
//function jsFireThePreviewClick() {
// var ctrl = $("#ImageButtonRUNTHEREPORTXD");
// if (ctrl != null) {
// ctrl.click();
// }
//}
// Add client-side hub methods that the server will call
$.extend(RPT.client, {
updateReportProgress: function () {
},
ReportOpened: function () {
//scrollRPT();
},
ReportClosed: function () {
stopRPT();
},
ReportCancel: function () {
return init();
}
});
// Start the connection
$.connection.hub.start()
.pipe(init)
.pipe(function () {
return RPT.server.waitForReportToBeReady();
})
.done(function (state) {
if (state === 'Open') {
RPT.client.ReportOpened();
} else {
RPT.client.ReportClosed();
}
// Wire up the buttons
$("#LinkButtonPreview").click(function () {
RPT.server.openReport();
});
$("#close").click(function () {
RPT.server.closeReport();
});
$("#LinkButtonCancelPROGRESSXD").click(function () {
RPT.server.cancelReport();
alert('Report Canceled By User');
});
});
});
If I move the LinkButtonPreview outside of the update panel, it works fine every time. I need to have this linkbutton inside of the update panel, but need it to work every time using the SignalR. I know it has something to do with the update panel and the way it handles the postback. However, I can not figure out what I need to do in order to get this to work correctly every time. Like I said, it does work the first time, but after that it does not.

As you suspected, the issue is related to the update panel. You're adding a click event handler to the #LinkButtonPreview button, but that button element only exists until the update panel refreshes. When the update panel updates, a new button is created with the same id but without the event handler that was attached to the old button.
The solution is to attach your click event handler to an element that is never going to be updated/replaced so the event handler isn't ever removed. You can still have the event handler only respond #LinkButtonPreview clicks without attaching the event to #LinkButtonPreview directly using .on():
$(document).on("click", "#LinkButtonPreview", function(){
RPT.server.openReport();
});
Since document is an ancestor element of #LinkButtonPreview, the click event originating from #LinkButtonPreview will bubble up all the way up to document. If you don't specify #LinkButtonPreview as the second argument to .on(), the event handler will be triggered by any click on the page.
You should also attach your click event handler the same way for #LinkButtonCancelPROGRESSXD.

Related

HTML validation not working for input field loaded using Jquery

I have a form input field loaded by jquery based on user selection but the HTML form validation and even jquery form validation not working for the input field loaded by jquery.
<tr>
<td colspan="2">
<select name="usdtnetwork" required="required" id="usdtnetwork" onChange="getaddressForm()" title="Please select your USDT Network">
<option>::: Choose your USDT Network :::</option>
<option value="ERC20">ERC20 (ETH)</option>
<option value="TRC20">TRC20 (TRON)</option>
<option value="BEP20">BEP20 (BNB)</option>
</select>
</td>
</tr>
<tr>
<td colspan="2">
<div align="left">
<span id="showinputfield"></span>
</div>
</td>
</tr>
This is my jquery (Noticed I tried e.preventDefault() but can't figure what am doing wrong so I commented it out)
<script>
/*$('.thisbuyUSDT').click(function (e) {
var myForm = jQuery( "#catalog_formusdt" );
// html 5 is doing the form validation for us,
// so no need here (but backend will need to still for security)
if ( ! myForm[0].checkValidity() )
{
// bonk! failed to validate, so return true which lets the
// browser show native validation messages to the user
return true;
}
e.preventDefault(); */
function getaddressForm() {
//e.preventDefault();
$("#loaderIcon").show();
jQuery.ajax({
url: "usdt_form_field.php",
data:'usdtnetwork='+$("#usdtnetwork").val(),
type: "POST",
success:function(data){
$("#showinputfield").html(data);
$("#loaderIcon").hide();
},
error:function (){}
});
}
//}
</script>
you have to reset validation on form after add some element (after $("#showinputfield").html(data);) by :
myForm.removeData("validator").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(myForm );
if it doesn't work please share complete html and jquery code

How to avoid page refresh after button click event in asp.net/vb.net

In the following code when I click on my Clear_Button my OnClick event refreshes my page and I don't want that to happen. How can I prevent this from happening?
<dx:ASPxButton ID="Clear_Button" runat="server" AutoPostBack="false" CssClass="bordered-orange roundCorners toRight toMiddle" Text="Clear" Width="18%" Theme="Metropolis">
</dx:ASPxButton>
My Event :
Protected Sub Clear_Button_Click(sender As Object, e As EventArgs)
Author.Items.Clear()
End Sub
Thank you in advance for your answers
event.preventDefault(); will work
Try to use in frontend like javascript to clearing your data or refreshing your page without postback
<asp:Button ID="Clear_Button" runat="server" CssClass="bordered-orange roundCorners toRight toMiddle" Text="Clear" Width="18%" Theme="Metropolis" OnClientClick="return resetButtonClick();"Text="Reset" />
<script type="text/javascript"> function resetButtonClick() { $("#<%= txt1.ClientID %>").val("");$("#<%= txt2.ClientID %>").val(""); return false;}</script>
To prevent refresh, you can use:
<dx:ASPxButton ... OnClientClick="return false;" >
</dx:ASPxButton>
thank you for your answers !
I managed to make it work thanks to the <asp:updatepanel> element which allows not to refresh the page

Blazor | if there's any method to convert the Razor Pages to HTML

I'm using Blazor Sever to make a website.
And there's a need that i should convert my razor page to htmlpage.So taht i can use my HTMLtoPDF interface to let customers to download their project.DO you have any ideas?
Such as the following Razor page.There're many variables and custom components in this page,how can i convert it to a static HTML page? Thanks a lot !!!
<div id="ABS" class="text-left">
<table style="border:black solid;font-weight:bold;font-size:12px" width="1200" cellspacing="0" cellpadding="0" border="1">
<tr class="text-center" style="background-color: #99CCFF">
<td width="300">描述 <br> Description </td>
<td width="500">标准选项 <br> Standard Option</td>
<td width="400">备注 <br> Comments</td>
</tr>
<ABS_HU ABSTI_HU="#ABSTI.HU" IsExpended="#IsExpendAll" />
<ABS_WSS ABSTI_WSS="#ABSTI.WSS" IsExpended="#IsExpendAll" />
<ABS_SYSTEM ABSTI_System="#ABSTI.System" IsExpended="#IsExpendAll" />
<tr>
<td style="background-color: #CCFFFF" width="300" class="text-center">
</td>
<td width="500" class="text-center">
</td>
<td style="background-color: #CCFFFF" width="400">
</td>
</tr>
</table>
</div>
I assume the customer sees the report first and then click a button like "save."
The general idea is to let the client (browser) render your component, send the "raw HTML" back to the server, and then you can use your HTMLtoPDF.
Let's create the javascript function. Maybe there are ways to do it with vanilla js as well. You could add these lines to your _Host.cshtml file.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" ></script>
<script type="text/javascript">
window.copyHtml = function () {
return $("html").html();
};
</script>
In your Blazor component, inject IJSRuntime and call the method when the button is clicked.
#inject IJSRuntime js
#* all the other components here *#
<button class="btn btn-primary" #onclick="GenerateHtml">Save Report</button>
#code {
private async Task GenerateHtml()
{
String result = await js.InvokeAsync<String>("copyHtml", Array.Empty<Object>());
//in a wasm project, use HttpClient to send the data to the API
//as a "proof," it is sent back to the server
Console.WriteLine(result);
//send to HTMLtoPDF
}
}
In case the saving should be done without clicking a button, the Blazor component lifecycle can help. In the lifecycle of a component, when the rendering is finished, the method OnAfterRenderAsync is executed. So, you can override it and generate the HTML there.
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await base.OnAfterRenderAsync(firstRender);
if(firstRender == true)
{
await GenerateHtml();
}
}

Action buttons in ASP.NET Core 2.2 razor view

Suppose we're redesigning the view below:
The current code is:
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Url)
</td>
<td>
<a asp-action="Edit" asp-route-id="#item.BlogId">Edit</a> |
<a asp-action="Details" asp-route-id="#item.BlogId">Details</a> |
<a asp-action="Delete" asp-route-id="#item.BlogId">Delete</a>
</td>
</tr>
}
Our goal is to remove the Delete view that is linked in each row. Instead we would like to have a delete button that deletes the row upon confirmation without leaving the Index page (reload is fine).
How would one go about implementing such button? And is there any relevant documentation?
You can use ajax to issue a delete request so that user can stay during the deletion process. Once the ajax request is successful,you can remove the table row from the UI.
First, add a new attribute to your anchor tag, which you can use for your jQuery selector to wire up the click event.
<a asp-action="Delete" ajaxy asp-route-id="#item.BlogId">Delete</a>
Here I added an attribute called ajaxy
Now we will listen to the click event on anchor tags with this ajaxy attribute, stop the normal behavior( navigating to the href attribute value URL) and instead make an ajax call. To do the confirmation, you can use window.confirm API.
#section Scripts
{
<script>
$(function () {
$("a[ajaxy]").click(function (e) {
e.preventDefault();
if (window.confirm("Are you sure ?")) {
var $this = $(this);
var url = $this.attr("href");
$.post(url).done(function (res) {
$this.closest("tr").fadeOut(300, function (a) {
$(this).remove();
});
}).fail(function (jqXHR, textStatus, errorThrown) {
alert("error in ajax call!" + errorThrown);
})
}
});
});
</script>
}
Assuming your Delete action accepts the Id parameter.
[HttpPost]
public async Task<IActionResult> Delete(int id)
{
// to do : return something
}
If you just want to remove the extra 'delete' view, you can move the delete code from the delete page tot he index page and use a simple html-form. e.g.
<form method="post" asp-page-handler="Delete" class="btn-group-sm" >
<a asp-page="./Edit" asp-route-id="#item.Id" class="btn btn-warning">Edit</a>
<a asp-page="./Details" asp-route-id="#item.Id" class="btn btn-info">Details</a>
<input type="hidden" asp-for="#item.Id" />
<input type="submit" value="Delete" class="btn btn-danger" onclick="return confirm('Are you sure you wish to delete this q-Section?')" />
</form>
Rename the 'OnPost' function to 'OnPostDelete' and it will work. You can do the same for the 'delete' button on the details page.
Regards Ken.

asp button postback inside div with (display:none)

I have a html button that calls an asp button to dopostback, but nothing happens.
<input type='button' value='click me' id='btntoClick'/>
<div id='divServerBtn' style='display:none'>
<asp:button ID='myButton' runat='server' onClick='myOnclickMethod'> </div>
my jquery:
$(function(){
$("#btntoClick").on("click", function(){ $("#myButton").click(); })
});
OR
if I set the div to visible at run time, still clicking the button does nothing, it goes to codebehind but IsPostBack is false
$(function(){
$("#divServerBtn").attr("display", "");
});
Try something like this as a test, then modify your code accordingly. The main thing is to use OnClientClick, not OnClick. It is also important to include "return false;"
Your function:
<script>
function ShowMe() {
$(function() {
$("#divServerBtn").show();
});
}
</script>
Your aspx button and div example:
<div id='divServerBtn' style='display:none'>Me</div>
<br />
<asp:Button ID="Button1" runat="server" OnClientClick="ShowMe(); return false;" Text="Button" OnClick="Button1_Click" UseSubmitBehavior="False" />