Calling C# method (using PageMethod) from LinkButton without postback (MasterPage website) - javascript

I create several LinkButtons dynamically in an ASP page with MasterPage. In a separate JavaScript file, i have a JS function that changes the text of the LinkButton when clicked, i.e. "Yes" to "No" and vice-versa. It's sort of a "Like" button. So it's mandatory the page stays static when people click the LinkButton (would be annoying if not).
A C# method with parameters must be executed when the LinkButton is clicked.
I add this click property to the LinkButton, to use the method that is in a separate C# Class file:
MyLinkButton.Click += (sender, e) => { MyClass.MyClick(par1, par2); };
But the thing is, if i add the following property to prevent postback and keep the page static when LinkButton is clicked:
MyLinkButton.Attributes.Add("href", "javascript:;");
It no longer runs the MyClick method in the MyClass file.
So i tried to call the MyClick method from the JS code that does the "Yes" to "No" change on click using PageMethod.
In MyClass i added: the reference to System.Web.Services and put [WebMethod] above the public static void MyClick() method.
Also added a ScriptManager to my MasterPage file inside body/form and set the attribute EnablePageMethods="true".
The problem is, with or without the ("href", "javascript:;") attribute set on LinkButton, the PageMethod is not calling the MyClick method in the MyClass file. I tried the following two ways:
PageMethods.MyClick(par1, par2)
and
PageMethods.MyClass.MyClick(par1, par2)
And both aren't triggering the method. I appreciate any comments or suggestions.

The way a link button works is, its href points to the __doPostBack JavaScript method. This triggers a message to be sent to the server. Since you've replaced the href with javascript:, essentially "do nothing," that explains the behavior you're seeing.
If you want to send data to the server without reloading the page, you need to use AJAX. There are two main methods, one is the UpdatePanel, most people, including myself, would recommend against this model. Why? Well think of it this way, based on what you're telling me, you have a "like" button. I'd guess there are two pieces of data your server-side method needs, some ID to identify what they are liking and a Boolean to say like or not like. If you use an UpdatePanel, the entire ViewState has to roundtrip to the server. Additionally, the server will respond with the entire HTML contents of everything in the UpdatePanel. There are many good articles on the internet that go into more detail, here is one if you're interested, but I've summarized the points. If you're trying to build a lightweight, fast modern website, it's not the way to go. If you're trying to get something done quickly and don't want to write JavaScript, it might be, however JavaScript is pretty much a requirement for the modern web.
Alternatively, you can use straight AJAX. This requires you to put a method in your code behind decorated with the [WebMethod] attribute. This means it can now be called from JavaScript via AJAX. Using my example you'd have:
[WebMethod]
public static bool DoLike(string id, bool likeOrNotLike)
{
// Your implementation
}
Now, how do you call it. I'd recommend you use a framework such as jQuery to call the AJAX as it simplifies a lot of the syntax for you. With jQuery, you can simply do:
$.ajax({
type: "GET",
url: "MyPage.aspx/DoLike",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: { id: "123", likeOrNotLike: true },
success: function (msg) {
alert("It was called successfully");
},
error: function () {
alert("An error occurred calling it");
}
});
The code above sends two parameters to the DoLike method, "123" (the ID), and true (likeOrNotLike). You're method will be called with these parameters as if you had called it from C#. The framework takes care of all of that.
To add jQuery to your page, simply add a:
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
If you're against jQuery, I can modify my answer to use XMLHTTPRequest directly but it's more cumbersome.
As you can see, AJAX isn't magic though, you can't simply add [WebMethod] to your event handler and all will work. In fact, if you go the straight AJAX route, you're not even using an event handler, you're calling a server side method directly.
You can certainly do the UpdatePanel as some others have suggested here, it will work. It's just, in my, and many other opinions, overkill for AJAX. It was Microsoft's attempt at implementing AJAX without the developer having to do much. Just like with ViewState, it comes with a price. It's up to you if the price is tolerable.

my 2 cents: I think it's because you are trying to run server code without sending the necessary info to the server. Without postback you cant expect the server to process the event.
Not sure if there's a way to do that in ASP. Maybe you could use an AJAX call but I never used it for this specific purpose.

If you want to call the server without a postback, you have to use an UpdatePanel or a native Ajax function. In your case, I believe UpdatePanel is nicest one.
Put your fields and the button inside the UpdatePanel, then everything will work fine, just like magic.
To see how to use UpdatePanel, take a look at
https://msdn.microsoft.com/en-us/library/bb386454.aspx
https://web.archive.org/web/20211020102853/https://www.4guysfromrolla.com/articles/102407-1.aspx
http://ajax.net-tutorials.com/controls/updatepanel-control/

Related

ASP.NET How to reuse jQuery event handlers across more than one cshtml file

I have this method for adding a global event handler, so I can check on each ajax request whether a response header has been added and how to respond to that.
This works absolutely fine, but I need it in more than one view (cshtml). So rather than duplicating it in every file, is there a way I could extract this out so I can call it from other files or apply this globally to all my views?
$(document).ajaxSuccess(function(event, request, settings) {
if (request.getResponseHeader('ResponseHeader') === '1') {
window.location.href = '#Url.Action("Action", "Controller")';
}
});
The code itself isn't super important, just more about whether it's possible to reuse these across all my views without duplicating it. I was also thinking about creating a global event handler that would check the http status code response from all ajax requests, then respond to the codes appropriately i.e. redirect any 404 codes to a not found page for example. There must be a way to achieve this or something similar rather than copying this across every single ajax call?
The main language I use is C# and I'm a beginner with using JavaScript / jQuery, so any extra explanations would be greatly appreciated.
Thanks!
jQuery version: 1.10.2

AJAX: How to call javascript function from C# code behind AJAX method

I need to call a javascript function(CommentButtonShow()) from c# code behind ajax method. I am unable to achieve this.
Following is the C# ajax method,
[AjaxMethod(HttpSessionStateRequirement.ReadWrite)]
public string CheckPassword()
{
ScriptManager.RegisterClientScriptBlock(this, GetType(), "ScriptManager1", "javascript:CommentButtonShow();", true);
}
Below is the javascript function,
function CommentButtonShow() {
$("#ctl00_mainContentPlaceHolder_divEmailFriends").removeClass('hidden').addClass('show');
}
Please help me out.
Thanks.
You can call CommentButtonShow() function in the javascript inside the ajax call success event. you cannot call javascript function inside web methods. if it is a post back your code will work but for ajax call backs it wont work.
I am answering this to shed more light for those who are new to this cilent-side and server-side scripting and mix up when doing some interesting work to them :)
This is absolutely impossible to call a Javascript (client-side) function from within C# (server-side) code. I mean, even you really cant invoke a javascript back into the server-side code in any programming language on earth!
It is very simple. Server-Side code renders the client-side code. Since the client code (html/javascript) resides in the browser you don't have any hook for javascripts at least to get it in server-side and then invoke. But for Asp.Net provides you a hook that actually transforms client-side HTML controls (most HTML tags) into server-side controls (as the .net framework supports) and then you can access their properties and some methods which only invoke at server-side. It does not mean that you have javascript events or such. Whatever you do with those server-side controls HAPPEN only at server-side and everything with that is COMPLETED before the final code of THAT control is sent to the browser to render. That is why when the html of such controls is rendered you see a typical .net based ID generation which looks like _ctr01 and such.
Anyway, using Ajax (at client-side) you can still invoke server-side methods using Ajax.Net and/or Ajaxpro (ajaxpro.info) or a custom javascript lib (jquery).
I hope this helps only in understanding what you are doing is actually NOT possible. I still would not rate your question negative as it is really going to help many new comers to understand how things work and how people who have gone through this got it right.
I hope its very fair use of this forum to provide the information that helps everybody rather negating their points without letting them know what they are asking/answering is right/wrong.
Thanks a lot.
We can call a method in codebehind from the JQuery AJAX call and depending upon the status whether it is error or success the corresponding method will be executed.
function MyMethod() {
$.ajax({
type: "POST",
url: "CodeBehind.aspx/ClearData",
contentType: "application/json;charset=utf-8",
data: '',
dataType: "json",
success: function (data, textStatus) {
closePopUpwindow1();
},
error: function (data, textStatus) {
closePopUpwindow2();
}
});}
[WebMethod]
public static void ClearData(){
Page.SetGridSessionData(gridID, null);
}
If the server side method is successfully executed then closePopUpwindow1 method is executed else closePopUpwindow2 method will be executed.

How to make sure that a Javascript function is called after EVERY postback in Liferay/ICEFaces?

I have very little experience with Liferay and ICEFaces. I need to build a portlet that calls a specific Javascript function every time a postback occurs.
In fact, when the form is submitted through AJAX, a loading screen appears and blocks the screen. When the postback completes, I need to take it out and give control to user again.
I have tried to put the <script> snippet in the portlet's body and it succeeds in executing when the page is first loaded (it's ok) and also when a postback changes the page's HTML content.
The problem is, when the server doesn't change the HTML (ie. a search returned with no result, you search again and you still get no results) the function is not executed again.
Even if I could post some code, I have very little idea of the architecture the web application is built on. What I gave here is all the information I have. By editing the javascript function to emit alerts when it's called I found the behaviour of the page.
Can you help me with that?
Have you tried the following:
<script>
Ice.onSendReceive('document:body',
function(){/*Before send ajax request*/},
function(){/*After receive the response*/}
);
</script>
But this solution applied for every ajax request you made, hope this can help you.
I made it using a weird trick with random numbers I want to share.
First, in the backing bean property I created a method
public String getLoadFunction()
{
return "functionName("+ new Random().nextDouble() +");";
}
and then
<script>
#{MyViewBean.loadFunction}
</script>
"Simply", ICEFaces is so smart it checks if the HTML has been modified or not when processing AJAX requests. This trick is very similar to appending a random number to HTTP URLs to avoid caches.

Postback without a control context

I have a situation where I want to use several server side controls, which have clients side state. I want to check the state when events occur (like various clicks), and when the state is where i want it, I want to postback to the server and do some processing.
In particular, I need to make sure that at least 3 different controls have selections before I want to do a postback. Since there is no specific control that will initiate the postback, I just want to capture the selection events on the client side, then call __doPostBack() (or something similar) to initiate the processing. So i have disabled all server side events, turned off autopostback, and have wired up some javascript to handle this.
I've got all the client side code written and working, however I cannot seem to get the server-side to recognize the postback. I'm overriding RaisePostBackEvent, and checking the eventArgument for my custom argument. This doesn't work, as RaisePostBackEvent is never called.
This method has worked when I had autopostback enabled (for example, the Telerik Radgrid OnSelectChanged server side event).
Any suggestions on the best way to handle this?
Update:
When asked for sample code, it's exactly as I say above. Not rocket science.
Javascript:
function CheckState(source, eventArgs) {
// logic to test state of controls
__doPostBack("", "DoMyWork:");
}
Then in code behind I have:
protected override void RaisePostBackEvent(IPostBackEventHandler source, string eventArgument)
{
if (eventArgument.IndexOf("DoMyWork") != -1)
{
// do my server side work.
}
}
RESOLUTION:
Because this is somewhat confusing.. I'll just say what my solution was.
I used one of the controls involved in the postback and used it's UniqueID for the control parameter, then my method as the event.
if you call the __doPostBack() without parameters, asp.net cannot figure out which control fired the event and thus it cannot determine which event to fire.
you need to add the name of the control as a parameter to __doPostBack() and an argument which could be null if you dont need one
__doPostBack('textbox1','') //no arguments
__doPostBack('textbox1','12')
you can read the argument you passed in from code behind like this:
Dim arg As String = Request("__EVENTARGUMENT")

When is a postback not a postback? (according to ASP.net)

Is there a difference between me using Javascript to redirect to URL + "?Querystring=value" versus using whatever mechanism ASP.NET uses?
If there is a difference, how can I make the rendered ASP.NET page be submitted to the same URL with a different query string by javascript?
If you want to do a post back just like a asp control like a asp:Button you can use the javascript functions included by the framework to do so:
__doPostBack('ControlIDOfEventYouWantToRaise','');
You can read more about the __doPostBack in this article:
Doing or Raising Postback using __doPostBack() function from Javascript in Asp.Net
Just doing a form.submit() will not be exactly the same as using __doPostBack.
To answer the first part of your question there is no difference doing a redirect if you are just doing a Response.Redirect as the will both do a GET. The difference is if you use a asp:Button control for instance, it will access your page first to handle the button (a post back) and then do a GET on the redirected page.
If you want to submit to the same URL (eg post your data) then you should use the __doPostBack method. If you don't require the data to be posted, then just do a redirect in javascript to the same URL with a modified query string (which will just do a basic GET) but your data will not be posted.
The only potential difference is that a querystring parameter is sent via GET, a form is (usually) sent by POST.
GET has a much smaller data limit as browsers have a max URL length (it varies)
You could use javascript to do a form.submit() which shoul emulate what ASP.Net does
I somewhat disagree with Basiclife's answer; if you have any code inside something like
if (IsPostBack) {
it's not going to be equivalent, ie the code is going to be executed if you're just setting the URL. Also, controls keep their state across postbacks but are freshly initialized if you're calling the URL again. This is due to ASP.NET trying to emulate a "normal" application, so the way to make sure a normal call and a postback have the same effect might result in "de-ASP.NET-ing" the entire page.
I'm not sure if what you want works. There probably is a way. But I heavily suspect there's a better way of doing this. If you get a postback for free, and can transmit data, why is it crucial that the data shows up in the URL, instead of being comfortably posted? I can see how you want a page to respond to a URL parameter, and how you might want to change the same parameter later on based on what's happening on that page, but since you always know you're posting back, you can eg override that URL parameter in that case, by something you're posting back. This doesn't sound so nice, but it might actually be less messy. Particularly since you seem to have a reason to not abandon the postback at all (otherwise you could just use a link, right?).

Categories

Resources