I have a javascript method looks like this
JSMethod(JS_para_1,JS_para_2)
{
......
,,,,,
}
and I have an ASP.NET method like this
ASP_Net_Method(ASP_Para_1,ASP_Para_2)
{
....
,,,
}
Now I want to call this ASP_Net_Method from my JSMethod by passing some parameters over there..
Just to be clear:
Your javascript is executed by the user's browser on the user's laptop
Your ASP.NET method is executed on your server
So, what you probably want to do is to send a message from the browser to the server saying "Hey, run this method and give me the result back".
If you are doing traditional ASP.NET development (not ASP.NET MVC), I think the normal approach would be to create an ASPX page which, when requested, executes the method you want executed. Then, in your javascript you just need to request this page. To do this, you can use jQuery (either jQuery ajax, jQuery get or jQuery post).
You will need to download the jQuery library and include it in your page for this to work.
Give it a go and if you can't get it to work, come back for more specific advice.
EDIT: You can also take a look at ASP.NET AJAX. The home page has a lot of tutorials and videos.
What you really want to do is execute server-side code (sometimes called "Code-behind", which was the term I used when googling this.) from javascript.
This post shows several options. The better ones are toward the bottom.
http://forums.asp.net/t/1059213.aspx
Basically, every function that fires a server side event uses a javascript method called __doPostBack and here is an example of what you want to do.
Ajax's PageMethods is very useful for this if you don't want to do a full postback and just need to call 1 method.
First I decorate a method in my aspx.cs file like so:
[System.Web.Services.WebMethod]
public static string getVersions(string filePath)
{ ...
return myString;
}
Notice the "static" too. Then in javascript I can call this like:
PageMethods.getVersions(_hfFilePath.value, LoadVersionsCallback);
You can have as many parameters as you need of different data types. The last parameter is the JavaScript function that gets called when the call returns. Looks something like:
function LoadVersionsCallback(result) {
...
// I make a drop down list box out of the results:
parts = result.split('|');
for (var i = 0; i < parts.length; i++) {
_ddl.options[_ddl.options.length] =
new Option(parts[i].replace(/~/g, ", "), parts[i]);
}
...
}
Finally, you must have the script managers property "EnablePageMethods" set to "true".
<ajaxToolkit:ToolkitScriptManager ID="ScriptManager1"
runat="server" EnablePageMethods="true"
EnablePartialRendering="true"
OnAsyncPostBackError="ScriptManager1_AsyncPostBackError">
</ajaxToolkit:ToolkitScriptManager>
So from JavaScript you can call a static function on your page's behind code.
Related
Obligatory "This works in my dev environment, but doesn't work on the server."
I have an ASP.NET 5 MVC project, using .NET Core, in which actions taken on a certain view trigger a "getJson" call in my javascript code, which in turn calls a function on the controller to obtain data from the server, in order to update the page without a postback.
When a valid entry is made in a textbox, this function is called in my javascript:
function getCustomerOptions(cn) {
$.getJSON('/Home/GetBillingCustomerByCustNum', { cust: cn }, function (data) {
// handle returned json data
}
}
... which calls function GetBillingCustomerByCustNum in my Home controller:
public async Task<JsonResult> GetBillingCustomerByCustNum(string cust)
{
var data = //[retrieve data from server thru repository function]
return Json(data);
}
In my dev environment, this works great. But after I publish the application to an IIS environment on a Windows Server 2016 machine, this fails. It seems that IIS is trying to call '/Home/GetBillingCustomerByCustNum' as though it were a view or a physical object, and so returns a 404 error.
I have tried altering my getJson controller call -- jquery function "getCustomerOptions" -- by adding
<%= Url.Content("~/") %>
so that the call becomes
$.getJSON('<%= Url.Content("~/") %>/Home/GetBillingCustomerByCustNum', { cust: cn }, function (data) { ...
but that still fails. According to the debugger console, the above url is being translated as
http://localhost/HC_RFQ/Home/%3C%=%20Url.Content(%22~/%22)%20%%3E/Home/GetBillingCustomerByCustNum?cust=[given value]
The only other step I could find suggested I prepare my url with an HTML helper, like so:
var url = '#Url.Content("~/Home/GetBillingCustomerByCustNum/")'
$.getJSON(url, { cust: cn }, function (data) {...
but of course that fails because HTML helpers don't work in separate javascript files. Var url is passed in as literally written.
Finally, I know this is not a case of my javascript files not being linked properly, because I can breakpoint my javascript in the debugger ahead of this failing call, and the breakpoints are hit at runtime.
What else can I try to fix this? Any advice is appreciated.
Have you tried a simple Home/GetBillingCustomerByCustNum, just without the starting /? From how you describe the error in production, that's basically a server issue when composing the final route to the controller.
Dropping the Home/ part works because you're calling that action from a view that resides on the same controller's folder path. Since you're using .NET Core, I suggest using the asp-action and asp-controller tag helpers as they let the server decide what's the actual route to the desired methods, even if you're POSTing or GETing without an actual postbacks. For example, this is what I do using javascript to call my methods on a form:
<form asp-controller="myController" asp-action="myAction">
and this is how I get my js code to retrive the corresponding url
let form = $(this).parents('form')[0];
let url = form.getAttribute('action');
the form doesn't have an actual submit button, so that the calls are all made from javascript.
I call a method in a separate Class file that needs to update a label.
[WebMethod] //needed for the AJAX call
public static void MyClick(int postid, int userid) //must be static
{
Page page = new Page();
//Page page = HttpContext.Current.Handler as Page //Pass the Page but don't work
MyClass.MyMethod(postid, userid, page);
}
The method MyClick() is called from an asp.aspx file (With MasterPage), to a separate MyClass.cs file.
I am not being able to get the Control (Label) with FindControl(). My guess is the "Page" is not being passed correctly. For what i've seen in debug, "page" comes with many exceptions.
((Label)page.FindControl("ContentPlaceHolder1_lbl)).Text = "foo";
This is the sequence:
1) User clicks sort of a "Like" dynamically-created LinkButton
2) There is a JS listener that on click changes to "Dislike" (example) and does an AJAX POST to aspx page method MyClick() with parameters (postid, userid).
3) MyClick() calls MyMethod(postid, userid) that is in MyClass.cs
4) MyMethod() does some SQL (was working) and updates the label (AJAX call not working since MyMethod() tries to set label to "foo").
You're not passing the current page, you're creating a new one:
Page page = new Page();
You could just pass a reference to the current page:
MyClass.MyMethod(postid, userid, this);
(Though in order to do that your page method shouldn't be static. In fact, in order to reference anything on the page instance that method shouldn't be static. See edit below)
However, in general it's best practice not to have other components rely on your page elements. Only the page's code should know/care about the UI elements it owns.
Instead of having the method set the value, have the method compute and return the value and then have the page set it. Something like this:
var result = MyClass.MyMethod(postid, userid);
myLabel.Text = result;
That way the external component isn't tightly coupled to this specific page, can be re-used by other pages, etc.
Edit: What you're trying to do physically won't work in the framework you're using. AJAX-invoked web methods are static for a reason. They don't maintain page state. So in the context of that web method there is no page and there is no label. The AJAX call is a simple service which accepts values and returns a response.
So even if you could update a label server-side, that's not going to do anything client-side. Your client-side code needs to update the markup in the browser. To do that, the AJAX call should simply respond with the new value and the JavaScript code should use that returned value to update the page. Something like this:
[WebMethod]
public static string MyClick(int postid, int userid)
{
return MyClass.MyMethod(postid, userid);
}
As in the earlier part of this answer, that external component should simply calculate and respond with the new value. It should not be coupled to the page. This web method should result in the client-side code receiving the updated value. Then, however you manage that client-side (you have no client-side code in the question), you would update the page markup with that resulting value.
I am currently trying to develop a chat applicaiton in asp.net2.0 and requires me to make a call to aspx Page Webmethod.My issue is that i cannot make a call to the page webmethod.
Not showing any message in error console of ff,so cannot findout where i have gone wrong.There is no issue while making a call webservice.
Heres the code i have writtern
$(document).ready(function(){
$("#btnSend").click(function(){
$.ajax({
type:"POST",
data:"{}",
url:"Chat.aspx/GetTime",
contentType:"application/json; charset=utf-8",
dataType:"json",
success:function(msg){
alert(msg.d);
},
error:function(msg){
alert(msg.d);
}
});
});
});
This is my chat.aspx page.The GetTime function is not getting called?Is the issue with the url ??
[WebMethod]
public static string GetTime()
{
return DateTime.Now.ToString();
}
Three things I would look at are:
1.) I'm wasn't sure that ASP.NET 2.0 could use the JSON AJAX stuff. I thought that came about in 3.5, but may be thinking of the ASP.NET AJAX implementation instead of jQuery's. See: Jquery's Ajax Property For Asp.Net 2.0, specifically:
You need to add this attribute to your webserver class
[System.Web.Script.Services.ScriptService]
public class Service : System.Web.Services.WebService
and this attribute to your functions
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
2.) You may want to check to see if the version of jQuery AJAX you are using is compatible with ASP.NET 2.0. I remember there being an issue there and needing to use older versions of jQuery (like 1.3) See: http://forum.jquery.com/topic/jquery-ajax-not-working-for-asp-net-2-0-7-5-2011
3.) This may be a long shot but is your page called Chat.aspx, or chat.aspx? Javascript capitalization matters (O;
Long shots, all of them, so good luck (:
[EDIT] Was just rereading the question and another idea popped in: Is the button from your .ASPX page? The reason I ask is because it's possible that when it's getting rendered on the page your button is no longer 'ID="btnSend"' but instead 'ID="ctl_btnSend_0897234h15807"' or so. If you have attached your jQuery to find '#btnSend' there's a chance that it's not the same ID in the DOM anymore.
Hoping that helps![/EDIT]
Whenever i want to add a javascript library programatically, say jquery for example, it generally involves making sure there is a placeholder at the footer of my page, then calling a codebehind method that will take a link to the src as a parameter and return an htmlgeneric control, which is then added to this placeholder.
Is this still the neatest way to do it, even with .net 4.0 out?
I think a better way is to use the RegisterStartupScript method:
http://msdn.microsoft.com/en-us/library/z9h4dk8y.aspx
And even better in your case RegisterClientScriptInclude:
http://msdn.microsoft.com/en-us/library/kx145dw2.aspx
EDIT:
Here's a sample of RegisterClientScriptInclude:
if (!Page.ClientScript.IsClientScriptIncludeRegistered("myJsInclude"))
Page.ClientScript.RegisterClientScriptInclude("myJsInclude", "myJsFile.js");
EDIT2:
Here's a sample of an include with RegisterStartupScript:
string jsBlock = "<script src='myJsFile.js'></script>";
if (!Page.ClientScript.IsStartupScriptRegistered("myJsInclude"))
Page.ClientScript.RegisterStartupScript(typeof(string), "myJsInclude", jsBlock, false);
You should add things like language="text/javascript" to the script tag, but for readability I didn't add them.
Sorry... I decided to move my comment to an answer.
I personally add all of my JS to the ScriptManager. It helps lower the number of Http calls that the page has to make.
ScriptManager1.CompositeScript.Scripts.Add(New ScriptReference("~/Page/To/Jquery.js"))
But this is only if you're already using a ScriptManager on your page
Also, if you don't want to add it from CodeBehind, you can do it right in your page.
<ScriptManager>
<CompositeScript>
<Scripts>
<-- your scripts in here -->
</Scripts>
</CompositeScript>
</ScriptManager>
So by doing this, you're able to add all of your JS to a single HTTP Request rather than having a bunch of different requests all at once.
Then in the ScriptManager tag, you can add LoadScriptsBeforeUI="false" to have them put to the bottom of the page.
Sorry but that was never the cleanest way to inject script into an asp.net page.
Look at the ClientScript object. There are several methods that will suit your needs without resorting to placeholders.
ScriptManager is a good way to do this, as mentioned above. If you are not using MS Ajax and ScriptManager, then I suggest you write your own control. It should be very simple control at that. Add a public variable List and override RenderContents method to walk through your list of strings and render on the page. Sample code:
public class CustomScriptManager : WebControl
{
private List<string> scripts = new List<string>();
public List<string> Scripts
{
get { return scripts; }
set { scripts = value; }
}
protected override void RenderContents(HtmlTextWriter writer)
{
foreach (string script in scripts)
{
writer.Write("<script language=\"JavaScript\" type=\"text/javascript\" src=\"" + script + "\"></script>");
}
}
}
P.S. I haven't verified above code, but I thing you get the idea.
I’m trying to create an error message / notification component for our .net C# web application. The requirements are that multiple messages can be posted, that they persist through partial post backs, and have different types (sticky, error, notification).
I have a server-side method that captures these messages, and I am using the popular jQuery plug-in jGrowl to display these messages. See below:
public void ShowErrorMessage(string Message)
{
Page.ClientScript.RegisterStartupScript(this.GetType(), "ErrorMessage", "<script type=\"text/javascript\">$.jGrowl('" + Message + "', { sticky: true });</script>");
}
Currently I am firing the jGrowl script inside the ShowErrorMessage method using RegisterStartupScript approach which works fine for the first message but of course the RegisterStartupScript does not allow me to to fire Javascript on a whim. How can I fire an instance of jGrowl each time ShowErrorMessage is hit?
My JavaScript knowledge is limited. I am open to any suggestions or alternative methods. Thank you.
Could you give a little more info. You mentioned doing partial postbacks. Are you doing a full postback or a partial? If partial, how so...through an updatepanel?
One thing to note is that the RegisterStartupScript will only register 1 instance of that script if it's always called from the same place. It's using this.GetType() and "ErrorMessage" to check to see if it's already been registered. If you call it with a different message, that script won't register since it's still the same type and "ErrorMessage".