I am trying to pass in an image from an image editor to a function in VB. I have it setup as the following:
JS
var canvas = document.getElementById("canvas_minipaint");
var img = canvas.toDataURL("image/jpeg");
__doPostBack('SaveImage', img);
ASPX
<asp:LinkButton ID="SaveImage" runat="server" Visible="true"></asp:LinkButton>
VB
Private Sub SaveImage_Click(sender As Object, e As EventArgs) Handles SaveImage.Click
Call GetSession()
End Sub
When I click the SaveImage button right now i get the following error:
Invalid postback or callback argument. Event validation is enabled using in configuration or <%# Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.
How do I register the onClick for the button for the validator? Or am I missing something else?
Turn off event validation for this page. You can turn it off at page level by adding
Page EnableEventValidation="false"
to the top of your .aspx page. I would recommend doing that in this case, since you are doing a manual postback using JavaScript. It is not possible to turn it off for individual controls.
EDIT:
You could always store the value of the image in a hidden field, and that would prevent the need to disable event validation. You'd need a way of storing the image data (base64 string maybe?) in the field, but it would work.
I would suggest not disabling the EventValidation to avoid malicious users to mess with the form. You could store the data in an input hidden or override the page event and handle it.
protected override void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument)
{
if (sourceControl is yourControl)
{
//sanitize data
}
}
Related
This is something I already know the answer to but I want to come up with a better way. I have a dropdown within a gridview. Within the method that populates the dropdown data I'm adding an an "onchange" attribute to the dropdown. The onchange calls a javascript function that is then used to fire a popup based on what the user selects on the dropdown.
My issues is I want the popup to display only once within that current page for that user. The easiest answer is to use JavaScript sessionStorage to store some dummy value that is checked before the javascript popup code is run and then set afterwards.
The problem I'm having is that I then have to manage the storage by either clearing the storage when the user goes to another page by attaching storage.clear to all the buttons dealing with moving to another page.
Is there a way that I can clear the storage after the person moves to another page other than the page they are on. BTW the dropdowns and javascript are all located within an ASP.NET custom control. That custom control is loaded within several pages, therefore I want the logic to be isolated within the custom control so that I don't have to make changes to every page that uses the control and for modularity.
You can in the page on load, just set a global js var to the page like this:
protected void Page_Load(object sender, EventArgs e)
{
string script;
if (IsPostBack)
{
script = "var isPostBack = true;";
}
else
{
script = "var isPostBack = false;";
}
Page.ClientScript.RegisterStartupScript(GetType(), "IsPostBack", script, true);
}
So, now in your js code, you can use isPostBack as a simple true/false var.
I've a legacy ASP.NET application, which I'm trying to modernize. I've a page
MyPage.aspx, and its codebehind MyPage.aspx.cs
I've replaced a custom user control (which does a fileupload) with a custom react component. The react component is working as expected. The old ascx usercontrol had an event handler which is defined in 'MyPage.aspx.cs'as follows.
protected void asyncFile_FileUploaded(object sender, FileUploadedEventArgs e)
//logic to set the uploaded file's name etc for saving.
}
Nowthat the custom control is replaced with an empty DIV, where the react component is being mounted, I'm left with no option to call my C# logic in the 'MyPage.aspx.cs' codebehind file.
I've created a 'CreateProperty.aspx.js' file which is responsible of initializing my react component inside the .aspx page, and below is the contents of this file.
$(document).ready(function () {
if ($('#Myupload').length) {
ReactDOM.render(
<Upload id="pictureupload2"
onChange={onChange}
setBusyState={onBusy}
onUploadSucceeded={onUploadSucceeded}
/>,
document.getElementById("Myupload")
);
}
});
function onChange(e) {
console.log(e);
}
function onBusy(e) {
console.log(e);
}
function onUploadSucceeded(e) {
console.log(e);
}
Once the react component has done the uploading, it calls the function onUploadSucceeded() with my required parameters. But how will I pass that value back to my MyPage.aspx.cs file ?
Please help.
Drop in a standard asp.net button on the form.
Move the code you have/had for the previous event into that button code stub
eg:
protected void asyncFile_FileUploaded(object sender, FileUploadedEventArgs e)
//logic to set the uploaded file's name etc for saving.
}
So, move the above code to the button (style="display:none) to hide it.
AND OF COURSE don't copy the event stub code!!!.
Now, in your js function, do whatever and simply "click" on that button.
The bonus here is you get the badly needed post back when the client side js/ajax runs.
So, you have this:
function onUploadSucceeded(e) {
console.log(e);
document.getElementById('<%= btnOkUpLoad.ClientID %>').click();
So, the above is nice. I mean you could do a js __DoPostBack(); in js, but then you have to pass some parameters, and then client side in the on-load page event, detect the parameters (a pain to wrire up).
So, anytime I want to run code behind from js? Just drop in a asp button, write the code stub for that button, and then client side, use the above ".click()" to run that code. As noted, in MOST cases you want a post back anyway - which is what a asp.net button does for you.
Edit: now I said we want a post back in most cases? Well, I mean when we are all said and done - and thus this button click makes sense. We certainly don't want needless post backs - but when you do, and when you want to run+call a code stub, the this button trick is nice. Just use style="display:none" to hide it from view - but js code can still use the .click() to run (click) the button for you))
I have a large .aspx page, with multiple server controls. And, there is also a JavaScript file referenced by this .aspx page. I want to have a JavaScript function within this existing .js file, that will get called before any postback that happens to the server.
[note: I have seen another post that mention how to do this in JQuery ( How to capture submit event using jQuery in an ASP.NET application? ), but I would like that to be done through the existing JavaScript file, rather than using a new technology like JQuery]
[Edited] Solution of using OnSubmit handler will not work for me...because it will not get called for postbacks that get triggered by server controls.
You need something like this:
/*
usually there is only one form in asp.net, but if you know you can have
more than one, you can get main form with document.getElementById
*/
var form = document.getElementsByTagName("form")[0];
if (form.addEventListener) {
form.addEventListener('submit', functionThatShouldBeCalledBeforeSubmit, false);
} else if (form.attachEvent) {
form.attachEvent('onsubmit', functionThatShouldBeCalledBeforeSubmit);
}
onsubmit event will rise any time form is submitted. No matter how.
More details about attaching events with JS: https://developer.mozilla.org/en-US/docs/DOM/element.addEventListener
I have a simple form (textbox, submit button) which is wrapped in an update panel.
<asp:UpdatePanel ID="ReplyUpdatePanel" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:Textbox id="ReplyTextBox" runat="server"/>
<asp:Button id="SubmitButton" OnClick="SubmitButton_Click" runat="server"/>
<ContentTemplate>
</asp:UpdatePanel>
So, when i click the button, the server-side click event is fired (SubmitButton_Click), stuff happens to the db, and the page is re-rendered (asynchronously).
Here's my issue - i need to execute some JavaScript after all the "stuff happens to the db".
In other words, i need to create some JavaScript whose data/parameters are based on server-side logic.
I've tried this:
Page.RegisterStartupScript
and this
ScriptManager.RegisterStartupScript
Neither work (nothing happens).
Now i now i can hook into the .add_pageLoaded function using the client-side AJAX libary (to execute client-side scripts once partial update is complete), but the problem is i need data from the server that is created on the button click event.
Ie:
Sys.Application.add_init(function () {
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function (sender, args) {
var panels = args.get_panelsUpdated();
for (var i = 0; i < panels.length; i++) {
// check panels[i].id and do something
}
});
});
The only "hack" i can think of at the moment is to do the above, but call a web service, getting all the data again then executing my script. I say "hack" because i shouldnt need to do an asynchronous postback, hook into the after-partial-postback event handler then call the server again just to get the info that was previously posted.
Seems like a common problem. And no, i cannot remove the UpdatePanel (even though i would love to), don't want to waste time arguing why.
Any non-hacky ideas?
EDIT
Clarification on the data i need sent to script:
I type some text in the textbox, click submit, then the server creates a database record and returns an object, which has properties like ID, Name, URL, Blah, etc. These are the values that the script requires.
So if i were to call a web service from the client-code, in order to get the values that were just created, i would need to do some hacks (get last record modified that has the value of the textbox). Not ideal, and neither is two AJAX calls for one form post. (update panel postback, then web service call).
Instead of add_pageLoaded you'll want add_endRequest here, like this:
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function (sender, args) {
//check here...
});
The difference is that endRequest runs when any partial postback comes back.
I have a ListView that contains playlists. If the user wants to edit an album, they click the edit link and it allows them to remove or add songs to the playlist. If the user wants to Save a new playlist while keeping the original one, the would click a Save As Button. Here is what should happen:
If the user clicks Save As and they have not changed the name, I want to display an alert telling them they must change the name.
If the user clicks the Save As and they have changed the name, I want to display an a confirmation that they actually want to save it.
Currently, what is happening is that if I put something like the following in my code behind, the script does not register until the second click and whatever script was registered stays registered meaning that if I end up changing the name and the alert script was registered before, it will display the alert instead of the confirmation. Here is the code:
if (newname == oldname)
{
btnSaveAs.OnClientClick =
"javascript:alert('Save As requires you to change the name of the playlist. Please
change the name and try again.');";
}
else
{
btnSaveAs.OnClientClick = "javascript:confirm('Are you sure you want to save the
playlist" + newname + "?');";
}
I also tried adding the return false so it would not do a postback, but if I do that, then it does not doesn't actually do anything when I click OK on the confirmation.
What SLaks said is correct, you're misunderstanding the page lifecycle. The javascript code needs to be in place on the page before you click Save As. In your example as described, the user makes changes to the title/name and clicks Save As, after which the javascript code is applied to the button. The second time they click Save As, the validation results from the previous example pop up.
Option 1: Use a validator control
The simplest way to solve this is to use a RegularExpressionValidator control to compare the values.
Markup snippet:
<asp:Label ID="lblName" runat="server" Text="Name: " />
<asp:TextBox ID="txtName" runat="server" />
<asp:RegularExpressionvalidator ID="valName" runat="server" ControlToValidate="txtName" ErrorMessage="You must change the name before saving" Display="Dynamic" />
<asp:Button ID="btnSaveAs" runat="server" OnClick="btnSaveAs_Click" Text="Save As" CausesValidation="True" />
In your code-behind once the form fields (album name, etc.) are bound, run this:
valName.ValidationExpression = string.Format("[^{0}]", Regex.Escape(lblName.Text));
The above regular expression will be valid for any input except what was there to begin with. If the user changes the text for the album name, the save button will validate correctly. If they do not, the validator will kick in and display a message on the page saying they have to change it.
Then handle the OnClick event of the save button only for saving the values, because it will only fire if the page was validated:
protected void btnSaveAs_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
//do you save actions as needed
}
}
You can also still use your confirm box as you wanted, by doing:
protected void Page_Load(object sender, EventArgs e)
{
btnSave.OnClientClick = "return confirm('Are you sure you wish to change the name?');";
}
The above should work just fine. An alternate approach is listed below:
Option 2: Use a clientside validation function
If you wanted to do the validation completely client side, you could but it will be far more complicated. What you'd need to do, is register a completely clientside validation function.
In your code behind during Page_PreRender:
protected void Page_PreRender(object sender, EventArgs e)
{
//define the script
string script = #"
function validateAlbumName(oldName, textBoxId) {
//get the textbox and its new name
var newName = document.GetElementById(textBoxId).value;
//compare the values
if (newName === oldName) {
//if the name hasn't changed,
alert('You must change the name of the album');
return false;
}
return confirm ('Are you sure you want to save the playlist ' + newName);
}
";
//register the client script, so that it is available during the first page render
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "SaveAsValidation", script);
//add the on client click event, which will validate the form fields on click the first time.
btnSaveAs.OnClickClick = string.Format("return validateAlbumName('{0}','{1}');", txtAlbumName.Text, txtAlbumName.ClientID);
}
Hope this helps. There are likely some syntax errors in the above as I just threw it together quickly..
The OnClientClick property is a Javascript string, not a URI. Therefore, you should not begin it with javascript:.
To handle the confirm correctly, write OnClientClick = "return confirm('Are you sure?');";
Also, you're misunderstanding the ASP.Net page model.
Your C# code-behind event handler only runs after the user clicks the button and after the OnClientClick callback. You need to write all of that in Javascript and call it in OnClientClick.