Pass ViewModal from javascript file to code-behind - json

I have a Javascript file that calls a method in my code-behind. This seems to work if I create a parameterless default constructor, EXAMPLE 1, BUT I want to pass to the save method my ViewModel, EXAMPLE 2. When I do this I get a 500 error. After digging deeper I discovered more details about that network error.
Parameterless Default Constructor - this works but only if the other constructor is commented out.
EXAMPLE 1
[HttpPost]
public JsonResult SaveWorkRequestDetails()
{
return Json(new {});
}
If I have both of these in the code-behind file then I get this error: The current request for action 'SaveWorkRequestDetails' on controller type 'WorkRequestController' is ambiguous between the following action methods:
System.Web.Mvc.JsonResult SaveWorkRequestDetails() on type WorkRequest.Controllers.WorkRequestController
System.Web.Mvc.JsonResult SaveWorkRequestDetails(WorkRequest.ViewModel.WorkRequestViewModel) on type WorkRequest.Controllers.WorkRequestController
EXAMPLE 2
[HttpPost]
public JsonResult SaveWorkRequestDetails(WorkRequestViewModel viewModel)
{
// TODO: Save logic goes here
return Json(new { });
}
I need to pass the viewModel in order to save the user's selections. I am missing something and I am not sure what.
RegisterUIEventHandlers: function () {
$('#Save').click(function (e) {
// Check whether the form is valid. Note: Remove this check, if you are not using HTML5
if (document.forms[0].checkValidity()) {
e.preventDefault();
$.ajax({
type: "POST",
url: WorkRequest.SaveUrl,
data: ko.toJSON(WorkRequest.ViewModel),
contentType: 'application/json',
async: true,
beforeSend: function () {
// Display loading image
alert(ko.toJSON(WorkRequest.ViewModel));
},
success: function (result) {
// Handle the response here.
},
complete: function () {
// Hide loading image.
},
error: function (jqXHR, textStatus, errorThrown) {
// Handle error.
}
});
}
});
}
In the alert you see in beforeSend, in the AJAX POST within the javascript above, I see the selections the user makes. Everything works so I just want to pass this to the Controller's SaveWorkRequestDetails, how can I do this please. I was my understanding that the data parameter passed this on to the method specified in the url parameter.

The error message is clear. You have two action methods with the same name. So, call to the SaveWorkRequestDetails is ambigious as the error indicates.
You can overload functions in C# but it is not possible in ASP.NET MVC Framework.
It is not possible to have two SaveWorkRequestDetails() actions with different method signatures on the same controller in ASP.NET MVC.
Just remove the first SaveWorkRequestDetails(), and you will be fine.

I changed the dataType to json instead of application/json. This resolved the issue of the error stating there was not a parameterless default constructor. Now SaveWorkRequestDetails is being called.
RegisterUIEventHandlers: function () {
$('#Save').click(function (e) {
// Check whether the form is valid. Note: Remove this check, if you are not using HTML5
if (document.forms[0].checkValidity()) {
e.preventDefault();
$.ajax({
type: "POST",
url: WorkRequest.SaveUrl,
data: ko.toJSON(WorkRequest.ViewModel),
dataType: 'json',
async: true,
beforeSend: function () {
// Display loading image
alert(ko.toJSON(WorkRequest.ViewModel));
},
success: function (result) {
// Handle the response here.
},
complete: function () {
// Hide loading image.
},
error: function (jqXHR, textStatus, errorThrown) {
// Handle error.
}
});
}
});

Related

AJAX/JSON MVC method not being called

The MVC controller method is not being called with the following code and the issue isn't clear. $("#screeners").val() returns a list of strings:
<script>
$(document).ready(function () {
$("#submitScreeners").click(function () {
var selected = $("#screeners").val();
$.ajax({
contentType: 'application/json; charset=utf-8',
dataType: 'json',
type: 'POST',
url: '/Applicant/PassScreeners',
data: "selected=" + JSON.stringify(selected),
success: function () {
$('#result').html('"PassScreeners()" successfully called.');
},
failure: function (response) {
$('#result').html(response);
}
});
});
});
</script>
Method in controller:
public void PassScreeners(List<string> selected)
{
Session["SelectedApplicants"] = selected.Select(e => Int32.Parse(e.ToString())).ToList();
}
If I understand you correctly, the "selected" parameter is being passed in as a null value. I believe this is because you are using an incorrect data format. You tell the server to expect JSON formatted data, but then pass it something more akin to a form value with '='.
Try removing the "selected=" bit from your data line and just pass the stringified list.
If that doesn't work, check the trace and post it. If the string you are posting is just comma separated or something it needs to be an array in order for the POST to work correctly.
Apologies if I've misunderstood.

Append additional HTML result in calling MVC action by Ajax in DNN8

I'm new in DNN development.
I have created a very simple module in Visual studio--- A textbox and a button.
I just want to call the action in a controller by click the button, then show the return result in the textbox.
The code call the action success, but not sure why append lots of HTML inforation in the result.
Here is the action in the controller:
public ActionResult test1()
{
return Content("Return something");
}
Here is the Ajax code from the View:
$(document).ready(function () {
$("#btnSub").click(function () {
//alert(this.action);
$.ajax({
type:"GET",
contentType:"application/text",
url: "#Url.Action("test1", "Sky")",
data:"",
dataType: "text",
success: function (data) { $("#txtResult").val(data); alert("Success!") },
error:function(){alert("Failed!")}
});
});
});
And here is the result show in the textbox:
Anyone can let me know why the HTML information returned? Actually, I don't need it.
Thanks
Unfortunately, as described in DNN8 MVC unsupported features, it's not yet possible to return a JsonResult. So the solution I used is to return an ActionResult (although the function returns Json):
public ActionResult Test()
{
return Json(new { success = true });
}
On jquery side, I setup ajax call to receive result as html. This avoid the browser to display a parsing error. Finally, just need to remove the html part and manually parse the response. It's not very clean, but the only solution I found until DNN support JsonResult.
$.ajax({
url: '#Url.Action("Index", "Contact")',
type: 'POST',
dataType: 'html',
data: $('#contact-form input').serialize(),
success: function (response) {
jsonPart = response.substring(0, response.indexOf("<!DOCTYPE html>"));
var data = JSON.parse(jsonPart);
if (data.success) {
alert("Great");
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert("Error!");
}
});
EDIT : Improved solution
DNN8 now support IMvcRouteMapper. You can then register a route in RouteConfig.cs. Once done, you can call the function using following URL :
/DesktopModules/MVC/ModuleName/Controller/Action
The action can return a JsonResult. But pay attention, if you just call that function, it will fail with a null exception on ModuleContext. You have to include in the ajax call the following header :
headers: {
"ModuleId": #Dnn.ModuleContext.ModuleId,
"TabId": #Dnn.ModuleContext.TabId,
"RequestVerificationToken": $("input[name='__RequestVerificationToken']").val()
}
You can find the module complete code here.
This is a working ajax call in DNN 9. You dont have to use #urlaction it will give whole html as well as data. dnn.getVar("sf_siteRoot", "/") +
"DesktopModules/MVC/ModuleName/Controller/Action", this does the trick and don't forget to add the header otherwise it will throw 500 error.
$.ajax({
url: dnn.getVar("sf_siteRoot", "/") +
"DesktopModules/MVC/ModuleName/Controller/Action",
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: "{ 'id':" + JSON.stringify(3543)+" }",
headers: {
"ModuleId": #Dnn.ModuleContext.ModuleId,
"TabId": #Dnn.ModuleCon`enter code here`text.TabId,
"RequestVerificationToken":
$("input[name='__RequestVerificationToken']").val()
},
success: function (response) {
debugger;
},
error: function (errmsg) {
alert("Error!");
}
});
Your controller should be
[HttpPost]
public ActionResult ActionName(int id)
{
var data = id;
return BuidJsonResult(true,data);
}
Happy Coding :)

Select2 ajax is correctly calling webservice, but then doing nothing after

I'm setting up a select2 with the following JavaScript
$j("#" + name).select2({
placeholder: "",
width:"300px",
minimumInputLength: 3,
ajax: {
url: "/MyService.asmx/ServiceMethod",
dataType: 'json',
data: function (term) {
return {
q: term // search term
};
},
results: function (data) {
alert('results');
return {results: data};
},
success: function() {
alert('success');
},
error: function () {
alert('error');
},
},
});
The method I'm calling is the following:
<WebMethod(enableSession:=True)>
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)>
Public Function ServiceMethod(q as String) As String
Dim temp As String = "[{'id':'35','text':'Drew'}]"
Return temp
End Function
I also have <ScriptService()> around the class. The enableSession is there because eventually I'm going to be running a lot of logic in the service that requires it, but for now I'm just trying to return a simple string with JSON.
I've put a breakpoint in the webservice, and I know it is being called. I know it is returning the JSON. I also know that the select2 expects "id" and "text" in the JSON return
My problem is the following: after I input 3 characters, the data function calls (I put an alert in it), the webservice breakpoint is hit, but none of the results, success, or error events fire afterwards. The select2 just spins and nothing ever happens. No javascript errors are entered in the console, and I'm at a loss about even where to look for information as to why the ajax isn't handling the returned value from the service.
Can anyone point me in the direction of at least where to look to see why this isn't working?
So I fixed this myself after getting a hint to look at the network log. The service was returning correctly, but it was returning XML, not JSON. I had to make 2 modifications and everything worked.
My working ajax:
ajax: {
url: "/MyService.asmx/ServiceMethod",
type: 'POST',
params: {
contentType: 'application/json; charset=utf-8'
},
dataType: 'json',
data: function (term, page) {
return JSON.stringify({ q: term, page_limit: 10 });
},
results: function (data) {
return {results: data};
},
},
The important changes were the type, putting the contentType in the params wrapper, and JSON.stringify-ing the data. I'm going to change what's passed and how its passed, but things are at least communicating now. Hope this helps anyone else who was looking for a similar solution.

how to return ajax suceess from user defined function [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I am having the bellow function .
Here i want to return ajax success from user defined function . How to do this
alert(Ajaxcall(id_array,"del"));
function Ajaxcall(id_array,type){
$.ajax({
type: "POST",
url: "serverpage.php",
cache:false,
data: ({id:id_array,type:type}),
success: function(msg){
return msg; //this returns nothing
}
});
alert(msg); // this one undefined
}
thanks
The "a" in "ajax" stands for "asynchronous" ("Asynchronous JavaScript And XML", although these days most people use it with JSON rather than XML).
So your Ajaxcall function returns before the ajax call completes, which is why you can't return the message as a return value.
The usual thing to do is to pass in a callback instead:
Ajaxcall(id_array,"del", functon(msg) {
alert(msg);
});
function Ajaxcall(id_array,type, callback){
$.ajax({
type: "POST",
url: "serverpage.php",
cache:false,
data: ({id:id_array,type:type}),
success: function(msg){
callback(msg);
}
});
}
It's surprisingly easy with JavaScript, because JavaScript's functions are closures and can be defined inline. So for instance, suppose you wanted to do this:
function foo() {
var ajaxStuff, localData;
localData = doSomething();
ajaxStuff = getAjaxStuff();
doSomethingElse(ajaxStuff);
doAnotherThing(localData);
}
you can literally rewrite that asynchronously like this:
function foo() {
var localData;
localData = doSomething();
getAjaxStuff(function(ajaxStuff) {
doSomethingElse(ajaxStuff);
doAnotherThing(localData);
});
}
I should note that it's possible to make an ajax call synchronous. In jQuery, you do that by passing the async option in (setting it false). But it's a very bad idea. Synchronous ajax calls lock up the UI of most browsers in a very user-unfriendly fashion. Instead, restructure your code slightly as above.
But just for completeness:
alert(Ajaxcall(id_array,"del"));
function Ajaxcall(id_array,type){
var returnValue;
$.ajax({
type: "POST",
url: "serverpage.php",
cache:false,
async: false, // <== Synchronous request, very bad idea
data: ({id:id_array,type:type}),
success: function(msg){
returnValue = msg;
}
});
return returnValue;
}
JQuery has a number of global Ajax event handlers, including $.ajaxComplete() and $.ajaxSuccess() (ref: http://api.jquery.com/ajaxSuccess/).
The code can be attached to any DOM element and looks like this:
/* Gets called when all request completes successfully */
$("#myElement").ajaxSuccess(function(event,request,settings){
$(this).html("<h4>Successful ajax request</h4>");
});
This code will execute whenever any successful Ajax call is completed.

Use JQuery AJAX Prefilter to Inspect Response Data And Conditionally Forward to 'Error' Event Handler

I may be way off course, but I was wondering if it's possible to use the JQuery prefilter functionality and analyze the response data in an Ajax Success and conditionally forward to the error event handler in my ajax calls based on the existence of certain elements in my returned JSON (error messages).
It would be nice if this was globally set for any ajax function in the page.
Maybe this isn't the best way to go about this; if anyone has an alternative idea, please let me know!
The prefilter:
//only run prefilter on ajax calls expecting JSON back in response, would this
//be the right way to do this?
$.ajaxPrefilter( "json", function( options, originalOptions, jqXHR ) {
jqXHR.success(function(data, textStatus, jXHR) {
if( hasErrors(data) ) {
//forward to error event handler?
}
});
});
Ajax call:
$.ajax({
type: "POST",
data: {
theData: "someData"
},
url: theUrl,
dataType: 'json',
cache: false,
success: function (data, textStatus, jqXHR) {
//do stuff on success
}
error: function ( jqXHR, textStatus, errorThrown ) {
//I want to do this stuff if data contains errors from server
}
});
Thank you so much!
Here's how I do it: I store the original success function (specific for each request), and then attach another callback. If it didn't have errors, I call the original callback:
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
var originalSuccess = options.success;
options.success = function (data) {
if(hasErrors(data)) {
//forward to error event handler or redirect to login page for example
}
else {
if (originalSuccess != null) {
originalSuccess(data);
}
}
};
});