Asp.net Ajax pageMethods not triggering success event handler - c#

I have asp.net ajax page method like following,
[WebMethod]
public static string UnAuthVote(string vf)
{
return "";
}
and I am calling it like this,
PageMethods.UnAuthVote("alikhan", success1, error);
And my success1 and error method written like following,
function success1(response) {alert("");
return false;
}
function error(error) {alert("error");return false; }
The problem is it's invoking error event. Why my code is not calling pagemethod's success event.
help
Thanks

Well, I was using url rewriting. So that's why my pagemethods was not working.
Well
I set set_Path property like following
PageMethods.set_path("Auth/profile.aspx")
Now it's working as it should

It helps if you show the actual error, for example:
function success1(response)
{
alert(response);
}
function error(error)
{
alert(error);
}
You can also use a debugger or developer tools to identify the problem. The error may show on the Console tab. The debugger will allow you to troubleshoot more efficiently than editing code to show alerts but I understand that in some cases this is preferable. You can also write to the console by doing:
function success1(response)
{
if(window.console) console.log(response);
}
function error(error)
{
if(window.console) console.log(error);
}
The benefit of this is it doesn't get in the user's way, and is only visible if the console is open. Checking for window.console avoids exceptions thrown from logging to console if it is unavailable.
If you don't know the properties of the return objects you can iterate through them like this:
function error(error)
{
var output = [];
for(key in error)
{
output[output.length] = key.toString() + " = " + error[key];
}
alert(output.join('\n'));
}

Related

SignalR version 1.2.2 client side method not being called, nor is console logging being made

I am using this tutorial: https://learn.microsoft.com/en-us/aspnet/signalr/overview/older-versions/tutorial-server-broadcast-with-aspnet-signalr to broadcast a message from Conext stored in singleton. I have a few issues.
First, there doesn't seem to be any issues from assigning the hub and making a connection from the client side. This is my code:
$(function () {
var transactionHub = $.connection.TransactPtHub; // the generated client-side hub proxy
transactionHub.client.broadcastDmrUpdate = function (test) {
alert("Yo-Yo Ma!!" + test);
};
console.log('test');
$.connection.hub.logging = true;
$.connection.hub.start()
.done(function () { console.log('Now connected, connection ID=' + $.connection.hub.id); })
.fail(function () { console.log('Could not Connect!'); });
if ($.connection.hub.state === $.signalR.connectionState.disconnected) {
alert("connected");
}
else {
alert("not connected");
}
});
My alert, "connected" does display on page load. The function in this part of the code, "transactionHub.client.broadcastDmrUpdate = function (test) {..." never gets called from the server side.
This is my singleton:
public class TransactPtSingleton
{
private readonly static Lazy<TransactPtSingleton> _instance = new Lazy<TransactPtSingleton>(() => new TransactPtSingleton(GlobalHost.ConnectionManager.GetHubContext<TransactPtHub>().Clients));
private TransactPtSingleton(IHubConnectionContext clients)
{
Clients = clients;
}
private IHubConnectionContext Clients
{
get;
set;
}
public static TransactPtSingleton Instance
{
get
{
return _instance.Value;
}
}
public void BroadcastDmrUpdate(string dmr)
{
Clients.All.broadcastDmrUpdate(dmr);
}
}
and this is my hub,
[HubName("TransactPtHub")]
public class TransactPtHub : Hub
{
public void UpdateDailyTransactionTable()
{
}
}
So, I don't get a call back to the client function on broadcast, and even though I set my logging to true, I am not seeing any logs inside of my browser console. Where do I begin to troubleshoot? Or what am I doing wrong? Thank you.
UPDATE: I misread my own diagnostics.
if ($.connection.hub.state === $.signalR.connectionState.disconnected) {
is triggering, so the connection is not starting for some reason. Also, the .done and .fail never get entered, and I never get any console messages.
Update 2: Combing through the SignalR.js it seems to have something to do with,
// Check to see if start is being called prior to page load
// If waitForPageLoad is true we then want to re-direct function call to the window load event
if (!_pageLoaded && config.waitForPageLoad === true) {
connection._.deferredStartHandler = function () {
connection.start(options, callback);
};
_pageWindow.bind("load", connection._.deferredStartHandler);
return deferred.promise();
}
as on return deferred.promise() it leaves the SignalR.js and comes back to the calling script in UI.
Figured it out. So this basically stems back to my original question here: Question Which initially stemmed from using SignalR 1.2.2 with JQuery version 3
From my "Update 2"
if (!_pageLoaded && config.waitForPageLoad === true) {....
That are was having issues because with the deprecation of .load in Jquery > 3 I needed to change .load to .on as per:
Breaking change: .load(), .unload(), and .error() removed
These methods are shortcuts for event operations, but had several API limitations. The event .load() method conflicted with the ajax .load() method. The .error() method could not be used with window.onerror because of the way the DOM method is defined. If you need to attach events by these names, use the .on() method, e.g. change $("img").load(fn) to $("img").on("load", fn).
From: JQuery Guide
But I goofed up and inside jquery.signalR-1.2.2js, instead of changing,
_pageWindow.load(function () { _pageLoaded = true; });
To
_pageWindow.on("load", function () { _pageLoaded = true; });
I did,
_pageWindow.on(function () { _pageLoaded = true; });
No console errors were being displayed so it made things tougher. But, SignalR connection now is established from the client side, and also SignalR logging is now working.
So if you are using an older version of SignalR with a newer version of JQuery, this may be your problem and solution.

how to pass a variable to a Page Method Success callback function

i'm using asp.net PageMethods.So here is the way i make a call to the method from javascript
function hello()
{
var a =10;
PageMethods.SaveData(JSON.stringify(basicInfo), SaveSuccessCallback, SaveFailedCallback);
}
And here is my success call back condition
function SaveSuccessCallback(response) {
//handle success code here
ShowEdit();
}
Now i wanted to handle the ShowEdit() based on a variable a which is in the hello function.
The issue is i don't know if its possible to pass a from hello to SaveSuccessCallback .
Note: i can't make a global.
You can use a closure:
var a = 10;
PageMethods.SaveData(
JSON.stringify(basicInfo),
function(response) {
SaveSuccessCallback(response);
ShowEdit(a);
}, SaveFailedCallback);
function SaveSuccessCallback(response) {
//handle success code here
}
You may prefer to make this a bit cleaner by wrapping up the closure in another method:
PageMethods.SaveData(
JSON.stringify(basicInfo), SaveSuccessCallback(10), SaveFailedCallback);
function SaveSuccessCallback(a) {
return function(response) {
//handle success code here
ShowEdit(a);
};
}

WPF Browser throws error

I am calling javascript functions from C# using the WPF variant of the browser control via InvokeScript.
I can call my function once without any problems. But when I call it a second time, it throws the following error :
Unknown name. (Exception from HRESULT: 0x80020006
(DISP_E_UNKNOWNNAME))
The Code I am using is the following :
this.browser.LoadCompleted += (sender, args) =>
{
this.browser.InvokeScript("WriteFromExternal", new object[] { "firstCall" }); // works
this.browser.InvokeScript("WriteFromExternal", new object[] { "secondCall" }); // throws error
};
The javascript function is :
function WriteFromExternal(message) {
document.write("Message : " + message);
}
I can call C# functions from the page via javascript just fine and invoke from C#, just can't invoke a second time. Regardless of what function I call.
I do not understand why it would fail the second time.
Thank you
Edit :
Did the following test (javascript) :
function pageLoaded() {
window.external.tick();
window.external.tick();
window.external.tick();
}
window.onload = pageLoaded;
function WriteFromExternal(message) {
document.write("Message : " + message);
}
And this is the C# side :
private int i = 0;
public void tick()
{
invoke("WriteFromExternal", new object[] { "ticked"+ i++ });
}
public static void invoke(string method, object[] parameters)
{
mainInterface.browser.InvokeScript(method, parameters);
}
And still throws the same error (after the first call), this suggests that it does not matter from where it is called, invoking the function from C# will throw this error if done more than once.
I assume you did the same as me and put your scripts in the body. For some reason when you call document.write from wpf it completely overwrites the document. If instead of using document.write you append a child it works fine. So change your JavaScript function to be:
window.WriteFromExternal = function (message) {
var d = document.createElement("div")
d.innerHTML= "Message : " + message;
document.body.appendChild(d);
}
// call from c#
WriteFromExternal("test")
It's been a while since I did something similar, but from what I remember your code looks correct. However, I do remember using a slightly different pattern in my project. Instead of delegating back to a JS method on the page I would make my ScriptingHost methods return values
EX:
C#:
public string tick()
{
return "some stuff";
}
var msg = window.external.tick();
document.write(msg);
If you have more complex objects than simple strings you can serialize them to JSON and parse them into an object on the JS side.
var jsonObj = JSON.parse(window.external.someMethod());
Not sure if you have the luxury of being able to change your method signatures in your scripting object, but it's at least an alternative approach.
Also, in your current implementation, have you tried to do something other than document.write? Do you get the same error if you display an alert box?

Running JavaScript in page from the backend (AJAX)?

I'm new to integrating JavaScript into a web site, but I'm going to need it often in my web site.
Here is an example:
Assuming I have the function:
showAlert()
Say I have:
<div id="some_div">
</div>
Could someone provide me some kind of example that would do this:
If I have a button and the user clicks it, this should raise an event in the backend and call some method in my C# file. Then my C# file should be able to call some other javascript method of the front end which would call showAlert() and display the alert in the div.
This is what I can't seem to find any information on.
The basic idea of passing information to and from the server. Any help with this would be really appreciated.
Thanks
Your best bet is to use a framework like jquery, then bind to the button, call the service, and handle the response. The below is a quick example of this.
$(document).ready(function()
$('#Button1').bind('click', function () {
// This grabs the page you are in so that you can call it correctly
var pagePath = window.location.pathname;
var testId = $("#some_div").val();
var url = pagePath + "/TestService";
$.post(url, { id: testId },
function (data) {
showAlert(data);
}
});
};
});
First, you need to make sure the document is ready at some point. Bind allows the the button to be bound when the document loads. Then, by clicking it, you execute the anonymous function that grabs the testId, calls your service, and handles the data response in a success callback.
Hope that gets you started in the right direction!
EDIT: Added backend webforms "service" exposure
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[WebMethod]
public static string TestService(string id)
{
var string = DBCollection.FirstOrDefault(x => x.id == id); // Or whatever you want to return the data
return "You called me on " + DateTime.Now.ToString() + "with " + string;
}
}
This would allow you to call the "WebMethod exposed on your page. For more help with this, please see the following link.
http://www.tugberkugurlu.com/archive/asp-net-web-forms---calling-web-service-page-methods-using-jquery
EDIT: Additional Considerations when performing this type of approach in webforms.
Calling a webmethod with jquery in asp.net webforms

Passing prompt box value from javascript function- PostBack to c#

I'll try to do the best I can to articulate what I'm trying to do.
Let me preface by saying that I am very new to C# and ASP.NET and have minimal experience with javascript.
I have a javascript function that invokes a prompt box. The overall picture is - if input is entered - it will be saved to a column in the database.
I'm drawing a blank on passing the value from the prompt box to the PostBack in c#.
function newName()
{
var nName = prompt("New Name", " ");
if (nName != null)
{
if (nName == " ")
{
alert("You have to specify the new name.");
return false;
}
else
{
// i think i need to getElementByID here???
//document.forms[0].submit();
}
}
}
This is what I have in C#:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//I have other code that works here
}
else
{
//I'm totally lost here
}
}
I'm trying to figure out how to make that call for the input from the javascript function.
I've spent the last few hours looking online and in books. Been overwhelmed.
EDIT
i did a little tweeking to fit what I'm trying to do....
<asp:HiddenField ID="txtAction" runat="server" Value="" />
document.forms(0).txtAction.Value = "saveevent";
document.forms(0).submit();
trying to figure out how to insert the string into the table now.....
string nEvent = Request.Form["event"];
if (txtAction.Value == "saveevent") {
nName.Insert(); //am i on the right track?
}
Well, here's one possible way (untested but should give you the basic idea). You could place a hidden field on your form to hold the value of the prompt:
<input type="hidden" id="hiddenNameField" runat="server" value="">
Then prompt the user for the value, set it to the hidden field, and then submit your form:
document.getElementById('hiddenNameField').value = nName;
document.forms(0).submit();
Then in your code-behind you can just access hiddenNameField.Value.
if you are trying to call the method on the back side using the java script you can try using the web method approach.
for instance you have a function that will call the SendForm method
function SendForm() {
var name = $("#label").text();
PageMethods.SendForm(name,
OnSucceeded, OnFailed);
}
function OnSucceeded() {
}
function OnFailed(error) {
}
and you have the method that will be called from javascript.
[WebMethod(enableSession: true)]
public static void SendForm(string name)
{
}
<script language='Javascript'>
__doPostBack('__Page', '');
</script>
Copied from Postback using javascript
I think you need AJAX request here. I suggest usage of jQuery, since do the dogs work for you... Otherwise, you will have to implement a lot of already written general code for AJAX processing.
Something as the following one:
function PromptSomewhere(/* some args if needed*/)
{
var nName = prompt("New Name", " ");
// Do process your prompt here... as your code in JS above. Not placed here to be more readable.
// nName is used below in the AJAX request as a data field to be passed.
$.ajax({
type: "post", // may be get, put, delete also
url: 'place-the-url-to-the-page',
data {
name: nName
// You may put also other data
},
dataType: "json",
error: PromptFailed,
success: OnPromptComplete
});
}
function PromptFailed(xhr, txtStatus, thrownErr) // The arguments may be skipped, if you don't need them
{
// Request error handling and reporting here (404, 500, etc.), for example:
alert('Some error text...'); // or
alery(txtStatus); // etc.
}
function OnPromptComplete(res)
{
if(!res)
return;
if(res.code < 0)
{
// display some validation errors
return false;
}
// display success dialog, message, or whatever you want
$("div.status").html(result.message);
}
This will enable you to send dynamically data to the server with asynchronous request. Now C#:
using System.Web.Script.Serialization;
protected void Page_Load(object sender, EventArgs e)
{
if(IsPostBack && ScriptManager.GetCurrent(this).IsInAsyncPostBack)
{
string nName = Request.Form["name"];
// do validation and storage of accepted value
// prepare your result object with values
result.code = some code for status on the other side
result.message = 'Some descriptive message to be shown on the page';
// return json result
JavaScriptSerializer serializer = new JavaScriptSerializer();
Response.Write(serializer.Serialize(result));
}
}
Notes: If you use ASP.NET MVC 2 or higher I think, you will be able to use JsonResult actions and Request.IsAjaxRequest (I think was the name), and many other facilities and improvements of ASP.NET - ASP.NET MVC is the new approach for creating web applications based on MVC pattern (architecture) and will replace ASP.NET Pages eventually in some time.
This is a very good resource and contains the answer to your question:
How to use __doPostBack()
Basically, call PostbackWithParameter() function from your other JS function:
<script type="text/javascript">
function PostbackWithParameter(parameter)
{
__doPostBack(null, parameter)
}
</script>
And in your code-behind, grab the value for that parameter like so:
public void Page_Load(object sender, EventArgs e)
{
string parameter = Request["__EVENTARGUMENT"];
}

Categories