Calling javascript function from within code using ClientScriptManager - c#

I have the following script tag included on the _layout page of my MVC application:
<script src="https://backpack.openbadges.org/issuer.js"></script>
This is used to issue badges on completion of courses. Thus far I have been issuing badges directly from the Views using javascript such as:
var postData = {
'badgeClassID': 1
};
$.ajax({
type: "GET",
cache: false,
url: "/Admin/NewBadgeAssertion",
data: postData,
success: function (dataBA) {
var myURL = dataBA;
OpenBadges.issue([myURL]);
},
error: function (error) {
alert("An Error has occurred during the Issue of this OpenBadge");
}
});
This is working for elearning courses that I have created but the completion of SCORM courses are recorded on close of the window and I now want to issue badges for SCORM courses through C# code behind rather than from the browser view.
How can I call OpenBadges.issue([myURL]) from code behind using ClientScriptManager. I have found the RegisterStartupScript method but I am not sure how to derive the type, key and script values. I have tried this:
ClientScriptManager csm = new ClientScriptManager();
csm.RegisterStartupScript(GetType(), "msgbox", "alert('SCORM BADGE HAS BEEN ISSUED FOR SUCCESSFUL COMPLETION');", true);
But I am not correctly defining any constructors

Try this:
First, on your view page, create a simple javascript function, which does what you need it to do, such as call OpenIssues.issue:
function myFunction(myUrl)
{
alert('test:' + myUrl);
OpenBadges.issue(myUrl);
}
And in your codebehind, you can call the javascript function:
String jscript = "myFunction('" + myUrl + "')"; //sending url as parameter
Page.ClientScript.RegisterStartupScript(this.GetType(),"myscript",jscript,true);

Related

How do I redirect to a new page from inside a class called by an ajax command?

I'm working with an asp.net MVC project. A coworker was new to MVC and handled all of the populating of data and click actions by using ajax calls. I know this isn't how MVC should be set up, but it's what I'm stuck with. I'm just trying to work around that the best I can. Anyway, within the method the ajax goes to, I need to redirect the user to a new page. How do I do that?
I tried Response.Redirect, but I got an error saying it didn't exist. I tried to add a using class, but couldn't it to work.
I found System.Diagnostics.Process.Start, but it opens in a new browser tab. Could there possibly be a way to open in the same tab?
So here's the ajax call. This is triggered in a javascript function when the user clicks a button:
$.ajax({
contentType: "application/json",
dataType: "json",
type: "post",
url: "/api/WoApi/PostWoApprGen/" + vUsr,
data: JSON.stringify(invObj),
success: function (res)
{
if (res)
{
var inv = $('#DivInv');
inv.html(res);
output = $('#TmpMsg');
output.html("");
opStatMsg("success", "rptGenWin");
}
else
{
opStatMsg("error", "rptGenWin");
}
}
});
That goes to a class in the controller directory, filename WoApiController.cs:
public string PostWoInv([FromBody] Koorsen.OpenAccess.WrkOrdTemp obj)
{
var currentUser = ClsUtility.GetCurrentUser();
if (currentUser == 0)
{
rep.UpdateWorkOrderStatusInvoiced(obj.WoTempId, currentUser, obj);
}
else
{
System.Diagnostics.Process.Start("~Admin/Login");
}
.............
.............
In your success callback, simply do
location.href = 'Home/Index';
or, preferably, using Razor and a method called Index in HomeController
location.href = '#Url.Action("Index", "Home")';

absolute path on call ajax mvc4 c#

i have a project in mvc 4 entity framework and call the controller method with ajax.
My problem is when i am using my app local, url is "Controller/Method" but when i publish i have to change url to "http://domain/appName/Controller/Method"
who can i do to get absolute path on ajax url??? my ajax is on js file and i can't use function like html.actionlink
example:
$("#btnAnswer").click(function () {
$.ajax({
url: "http://domain/appName/Controller/method/",
//url: "/Controller/method/",
data: { answer: $("#answer").val(), question_id: $("#question_id").val(), answer_id: $("#answer_id").val() },
success: function (result) {
alert(result);
}
}).error(function () {
}).fail(function () {
});
});
You don't really need the absolute url. Correct relative url is fine.
You should use the Url.Action helper method to generate the correct relative path to your action method. This will generated the proper path irrespective of your current page/view.
url: "#Url.Action("ActionMethodName","YourControllerName")"
Url.Action helper method will work if your javascript code is inside a razor view. But if your code is inside an external js file, you should build the relative url to your app root using Url.Content("~") helper method and pass that to your js code via a variable as explained in this post . Try to use javascript namespacing when doing so to prevent possible conflict/overwriting from other global variables with same name.
EDIT : Including Marko's comment as an alternate solution. Thank you :)
If it is an anchor tag, you can simply use the href attribute value of the clicked link.
Delete
and in your js code
$("a.ajaxLink").click(function(e){
e.preventDefault();
var url = $(this).attr("href");
//use url variable value for the ajax call now.
});
If it is any other type of html element, you can use html5 data attribute to keep the target url and use the jQuery data method to retrieve it in your js code.
<div data-url="#Url.Action("Delete","Product")" class="ajaxLink">Delete</div>
and in your js code
$(".ajaxLink").click(function(e){
e.preventDefault(); // to be safe
var url = $(this).data("url");
//use url variable value for the ajax call now.
});
As you are using this in a js file you can do something like this:
$("#btnAnswer").click(function () {
var hostString = window.location.protocol + "//" + window.location.host + /";
$.ajax({
url: hostString + "/appName/Controller/method/",
//url: "/Controller/method/",
data: { answer: $("#answer").val(), question_id: $("#question_id").val(), answer_id: $("#answer_id").val() },
success: function (result) {
alert(result);
}
}).error(function () {
}).fail(function () {
});
});

Pass parameters to a SQL procedure in .ashx

I have a C# Web Forms application that is displaying a jqGrid on the home page. I struggled with the jqGrid for a while as it was returning the "jqGrid is not a function" error on any page that inherited from site.master.
To solve this, I put the code and script references for the grid in a user control and then referenced the control on the home page:
<%# Register TagPrefix="My" TagName="GridControl" Src="~/UserControls/Grid.ascx"%>
<My:GridControl ID ="gridControl" runat="server" />
Inside Grid.ascx I have the code to populate the grid which gets it's data from a stored procedure inside a handler:
<script type="text/javascript">
$(function () {
$("#dataGrid").jqGrid({
url: 'Handler1.ashx',
datatype: 'json',
I used the handler along with Newtonsoft JSON.NET to avoid the json string length error.
The stored procedure has 11 parameters which when set to NULL, return all rows, which is what I want for the initial page load.
sqlCmd.Parameters.Add("#ProjNum", SqlDbType.Int).Value = DBNull.Value;
So now, I want to filter the results based on values from dropdowns on Default.aspx. The dropdowns are populated from SQL calls as well. But my question is how to get the values from the dropdowns into my handler?
I know I can do something like url: Handler1.ashx?asgnID=19 where I've just hardcoded the value, and then get it from the context.Request.QueryString, but I still don't know how to pass the value.
I've also read about using session, and I've tried passing a json string in ajax from default.aspx in a java button click event - which didn't work because the handler ends up getting called twice. I'm a little green on this stuff, and was hoping for a better alternative.
In case anyone is having the same issue, I did the following to solve it:
Create a function to extract the parameter from the url.
function GetParameterValues(param) {
var url = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for (var i = 0; i < url.length; i++) {
var urlparam = url[i].split('=');
if (urlparam[0] == param) {
return urlparam[1];
}
}
}
Assign the parameter value to a variable and use it in your Jqgrid url:
$(function () {
var id = GetParameterValues('id');
$('#statusGrid').jqGrid({
url: 'Handler2.ashx?id=' + id.toString(),
datatype: 'json',
mtype: 'POST',
colNames: ['Status', 'Status Date', 'Status Time',...
And, inside the handler, extract the id from the context in ProcessRequest()
int ProjNum = Convert.ToInt32(context.Request["Id"]);

JQuery code to call a c# method not working

I am calling a C# function from JQuery but it is giving error.
The JQuery function is written in ascx file and C# function to be called is written in that page's code behind. I am loading the user control into an AJAX tab on tab change event.
Googling, I got that I can not call C# function written in user control. So I written a function in host page(ASPX) and this function is calling my user control function.
But the AJAX request is some how failing, I don't know where. But interesting thing is I have kept a debugger in the error function and I checked the error object.
Status is 200, Status is OK, readyState is 4
and ResponseText is the markup of the page. This means the page is served but the kept the break point in the C# function. It never hits.
I have no idea what's happening. Also this is the first time I am calling a C# function from front end. I don't have detailed idea of what happens under the hood. Please help. Below is the code:
JQuery
$(function () {
$(".hint ul li").click(function () {
// remove classes from all
$(".hint ul li").removeClass("active");
// add class to the one we clicked
$(this).addClass("active");
//Ankit J, Implement logic to call jquery
var Availability = this.childNodes[0].innerText.trim();
debugger;
$.ajax({
type: "POST",
url: "../Pages/MyPage.aspx/CallUCMethodFromJQuery",
data: "{'sAvailability' : 'Availability'}",
dataType: "json",
success: fnsuccesscallback,
error: fnerrorcallback
});
});
});
function fnsuccesscallback(data) {
alert("success-->" + data.d);
}
function fnerrorcallback(result) {
debugger;
alert("error-->"+result);
}
ASPX page's code behind function
[System.Web.Services.WebMethod]
public void CallUCMethodFromJQuery(string sAvailability)
{
MyNamespace.UserControls.ControlName m = new UserControls.ControlName();
m.EditAvailabilityValue(sAvailability);
}
And then the UserControl's code behind
public void EditAvailabilityValue(string sAvailability)
{
}
Sorry for not mentioning.... JQuery is in the User Control because the source of click event is a li element which is in the User Control. Also the UserControl is in a folder UserControls and the host page is in the Pages folder and both these folders are in root folder.
Add contentType: "application/json; charset=utf-8" attribute to your ajax call:
$.ajax({
type: "POST",
url: "../Pages/MyPage.aspx/CallUCMethodFromJQuery",
data: "{'sAvailability' : 'Availability'}",
dataType: "json",
contentType: "application/json; charset=utf-8",
success: fnsuccesscallback,
error: fnerrorcallback
});
then change EditAvailabilityValue method in the user control to static:
public static void EditAvailabilityValue(string sAvailability)
{
}
and change CallUCMethodFromJQuery method in the aspx page code behind to static so it can be called using jQuery:
[System.Web.Services.WebMethod]
public static void CallUCMethodFromJQuery(string sAvailability)
{
MyNamespace.UserControls.ControlName.EditAvailabilityValue(sAvailability);
}

Knockout html binding not working (bound to a function calling a partial view) in ASP .NET MVC

I have an ASP .NET MVC application, additonally I am using Knockout 2.0.0. I created a partial view which I would like to render to the page using knockout. The partial needs to be rendered within a Knockout foreach statement. I am unable to get the knockout HTML binding to work, and so I'm currently using a hack to put the html into the div using JQuery.
There is a lot of html on this page, so it's not possible to post all of the source code, so I will try and post the pertinent code:
<div data-bind="foreach:issues">
#* SNIP - A lot of other html here*#
<div id="myPartialDiv" data-bind="html: $parent.getHtml(issueId())">
</div>
</div>
Further down I have the following javascript function on my KO View Model (I have commented out my hack and included the code that returns HTML):
var getHtml = function (issueId) {
var baseUrl = '#Url.Action("GetHtmlAction","MyController")';
$.ajax(
{
type: "POST",
url: baseUrl,
data: "&issueId=" + issueId,
success: function (data) {
//$('#mypartialDiv').html(data);
return data;
},
error: function (req, status, error) {
//$('#myPartialDiv').html('Something went wrong.');
return 'Something went wrong.'
},
dataType: "text"
});
}
The code above results in no data being rendered to the page. USing Chrome debug tools, I see that there are no javascript errors occuring, and knockout is simply not binding the html of the div to the results returned from the getHtml function.
What am I doing wrong?
Thanks
As Miroslav Popovic explains, the problem is that the AJAX request is asynchronous, so the return data is ignored and there is no return value from your call to getHtml.
I would suggest using a custom binding that handles the asynchronous HTML loading (I've put a working example here).
This works by taking 2 parameters to the asyncHtml: a function to call that takes a success callback as it's final parameter (plus any other parameters) and an array of the parameters that need to be passed to that function.
<div id="myPartialDiv" data-bind="asyncHtml: { source: getHtml, params: [123] }">Loading...</div>
The custom binding then grabs these values, concats a custom callback onto the parameters that are passed to it, and calls the specified function:
ko.bindingHandlers.asyncHtml = {
init: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
var parameters = value.params.concat([function(data) {
$(element).html(data);
}]);
value.source.apply(null, parameters);
}
};
Finally we can re-implement our view model HTML-retrieving method to make the POST call and invoke the new success handler:
var ViewModel = function() {
this.getHtml = function(issueId, callback) {
$.ajax(
{
type: "POST",
url: "/echo/html/",
data: {
html: "<p>server response " + issueId + "</p>",
delay: 1
},
success: callback,
dataType: "text"
});
};
};
Note: for this example I am using the jsFiddle echo to post back a random response
$.ajax is an asynchronous call. When you call it, the execution will just continue to the next statement in the getHtml function. Since this is the last statement, the getHtml function will return undefined.
About your return data;... This return is within a success callback function. The data will be result of that function, not the parent getHtml function. Besides, getHtml is already completed. You can't return a result from it.
How about having an observable property in your view model called html, and then find some other means of triggering the getHtml function (button click, some other success callback, issueId property change...), that will in turn set the 'html' property value. Then you could simply data-bind to that property data-bind="html: html".

Categories

Resources