Calling an ASP.NET MVC-view via ajax does not work - javascript

I am trying to call a view with an ajax-Call, passing an Id to the Controller-method. The Id is passed, everything is fine until I call the view in the return-Statement. Nothing happens.
$("#btnCreatePackage").click(function () {
var workflowId = $("#workflowId")[0].value;
$.ajax({
url: '#Url.Action("Create", "package")',
type: 'get',
data: { id: workflowId },
success: function (data) {
return data;
},
timeout: 500
});
});
public ActionResult Create(int id) {
IList < Workflow > workflows = WorkflowService.GetWorkflowList();
ModifyPackageViewModel vm = new ModifyPackageViewModel
{
Package = null,
Workflow = workflows.SingleOrDefault(x => x.Id == id),
Workflows = workflows,
Hosts = ScalingService.GetHostList(),
SelectedHostNames = new List<string>(),
Factor = 1
};
if (!vm.SelectedHostNames.Any()) {
if (vm.Hosts.Any()) {
vm.SelectedHostNames.Add(vm.Hosts.First().Name);
}
}
return View(vm);
}
The curious thing is, if i#m calling the view via #Url.Action without passing the Id with the following code, it works.
<a href="#Url.Action("Create")">
<div class="submenu-item add">
neues paket anlegen
</div>
</a>
public ActionResult Create() {
IList<Workflow> workflows = WorkflowService.GetWorkflowList();
ModifyPackageViewModel vm = new ModifyPackageViewModel
{
Package = null,
Workflow = workflows.FirstOrDefault(),
Workflows = workflows,
Hosts = ScalingService.GetHostList(),
SelectedHostNames = new List<string>(),
Factor = 1
};
if (!vm.SelectedHostNames.Any()) {
if (vm.Hosts.Any())
{
vm.SelectedHostNames.Add(vm.Hosts.First().Name);
}
}
return View(vm);
}
In both cases the Controller-method is called, goes through to the end without errors, in the first case nothing happens, in the second case everything is fine.
Anyone any ideas??????
Thanks, daniel

You can't return the data from an ajax call. You can store it in a variable declared outside, or do something inside your success handler.
This works just as well with your success handler (success: function(data) ...). The main thing to remember is the scope of the data that is returned from your controller.
EX:
var outsideVariable; // You can store the data in here for later if you need to
$.ajax({
url: '#Url.Action("Create", "Package")',
type: 'GET',
data: { id: workflowId }
}).fail(function (data) {
// Fail handler
}).done(function (data) {
// Success, Do Something
YourFunctionThatProcessesData(data);
// Or store the data into a variable that has outside scope
outsideVariable = data;
}).always(function () {
//Do this no matter what
});
function YourFunctionThatProcessesData(data)
{
// do stuff with the data
}

At least I fixed it, I did not need an ajax-Call, instead I just used this:
$("#btnCreatePackage").click(function() {
var workflowId = $("#workflowId")[0].value;
window.location.href = '#Url.Action("Create", "package")/' + workflowId;
});
It can be that simple........

Related

Two requests in one time immediatly. ASP MVC + JQuery Ajax

MVC application (ASP.NET MVC, client: jquery).
Problem: The second ajax-request wait, when the first ajax request will done.
I need, when the first and the second ajax-requests executes immediatly in one time.
The page sends to server to determine the count of records (the first ajax-request), very long (~5-7 seconds).
The operator click the buttom to open the card to edit it (the second ajax-request, fast, get the Dto-model).
The user doesn't need to wait the first request, he wants to work immediatly.
As a result, in Chrome in network page, two requests in status 'pending'. The second waits the first.
Question, how can I send requests, to execute asynchronously ?
The first ajax-request:
`window.jQuery`.ajax({
type: 'POST',
url: Url.Action("GetCountBooks", "Book");
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: JSON.stringify({ typeBook: "...", filter: "..." };),
success: function (data) {
// show in UI page the count of books by filter and params
},
error: function (data) {
//show error
}});
public class BookController : Controller
{
[HttpPost]
public NJsonResult GetCountBooks(string typeBook, Filter filter)
{
var data = DbProvider.GetCountBooks(typeBook, filter)
if (data.Result == ResultType.Success)
{
var count = data.Data;
return new NJsonResult
{
Data = new { Data = count }
};
}
return new NJsonResult
{
Data = new { Error = "Error while counting the books." }
};
}
}
The second ajax-request:
`window.jQuery`.ajax({
type: 'POST',
dataType: 'json',
contentType: "application/json",
url: Url.Action("GetBookById", "Book"),
data: JSON.stringify({ id: bookId }),
success: function (data) {
// show jquery dialog form to edit dto-model.
},
error: function (data) {
//show error
}});
public class BookController : Controller
{
[HttpPost]
public NJsonResult GetBookById(int id)
{
var data = DbProvider.GetBookById(id)
if (data.Result == ResultType.Success)
{
var book = data.Data;
return new NJsonResult
{
Data = new { Data = book }
};
return new NJsonResult
{
Data = new { Error = "The book is not found." }
};
}
return new NJsonResult
{
Data = new { Error = "Error while getting the book." }
};
}
}
I Cannot union ajax requests into one! The user can send various second request.
You need a fork-join splitter to fork 2 tasks and join based on some condition.
For example here is my implementation:
function fork(promises) {
return {
join: (callback) => {
let numOfTasks = promises.length;
let forkId = Math.ceil(Math.random() * 1000);
fork_join_map[forkId] = {
expected: numOfTasks,
current: 0
};
promises.forEach((p) => {
p.then((data) => {
fork_join_map[forkId].current++;
if (fork_join_map[forkId].expected === fork_join_map[forkId].current) {
if (callback) callback(data)
}
})
});
}
}}
Pass any number of async tasks (promises) into fork method and join when all are done. The done criteria here is managed by simple global object fork_join_map which tracks the results of your fork-join process (global is not good but its just an example). The particular fork-join is identified by forkId which is 0..1000 in this example which is not quite good again, but I hope you got the idea.
With jQuery you can create promise with $.when( $.ajax(..your ajax call) )
In the end you can join your promises like this
fork([
$.when( $.ajax(..your ajax call 1) ),
$.when( $.ajax(..your ajax call 2) )
]).join(() => {
// do your logic here when both calls are done
});
It's my own implementation, there may be already-written library functions for this in jQuery - I dont know. Hope this will give you a right direction at least.
The solution is to add attribute to Asp Controller: [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
http://johnculviner.com/asp-net-concurrent-ajax-requests-and-session-state-blocking/

ASP.NET MVC call Controller Action with parameter from javascript function

I have web application in ASP.NET MVC C#. I want to call Controller Action method with parameters from javascript but I get always null for parameters.
In .js I have:
$.ajax({
cache: false,
url: this.saveUrl,
type: 'post',
success: this.nextStep,
complete: this.resetLoadWaiting,
error: Checkout.ajaxFailure
});
nextStep: function (response) {
if (response.error) {
if ((typeof response.message) == 'string') {
alert(response.message);
} else {
alert(response.message.join("\n"));
}
return false;
}
if (response.redirect) {
ConfirmOrder.isSuccess = true;
location.href = response.redirect;
return;
}
if (response.success) {
ConfirmOrder.isSuccess = true;
window.location = ConfirmOrder.successUrl;
//window.location.href = #Url.Action("Completed", "Checkout", new { customerComment = "test", customerDate = "2018-12-31" });
//window.location.href = '#Html.GetUrl("Completed", "Checkout", new { customerComment = "test", customerDate = "2018-12-31" })';
}
Checkout.setStepResponse(response);
}
in RouteProvider.cs I have:
routes.MapLocalizedRoute("CheckoutCompleted",
"checkout/completed/{orderId}/{customerComment}/{customerDate}",
new { controller = "Checkout", action = "Completed", orderId = UrlParameter.Optional, customerComment = UrlParameter.Optional, customerDate = UrlParameter.Optional },
new { orderId = #"\d+", customerComment = #"\w+", customerDate = #"\w+" },
new[] { "Nop.Web.Controllers" });
And finaly in Controller I have:
public virtual ActionResult Completed(int? orderId, string customerComment, string customerDate)
{
//some code here
}
I always get parameters value null and I don't know why. I try to call this Action with parameters on several diferent way like I saw on this forum but no success.
Did you add httpPost wrapper to your controller ?
[HttpPost]
public virtual ActionResult Completed(MyClass MyClassObj )
{
//some code here
}
in your Ajax code u didn't mention your Data type And Data try This Ajax
function Save () {
try {
var req = {
DeliveryCode: value,
}
$.ajax({
url: URL,
type: 'POST',
data: req,
dataType: "json",
async: true,
success: function (result) {
resetLoadWaiting()
},
error: function (e) {
}
});
}
catch (e) {
}
}
Mistake was in url string. Correct one is
ConfirmOrder.successUrl = "http://localhost:8079/checkout/completed/?customerComment=eee&customerEstimateShippingDate=2017-11-14"
I found this solution in this answer: Routing with Multiple Parameters using ASP.NET MVC
I dont need to update RouteProvider with new parameters. It is enough to put in in Controller Action method. Other things happen automatically.

Correct way of redirecting view on AJAX 'success' in MVC app

Question background:
I've implemented a search feature in the header of my MVC site. Its features a input text-box with a 'Search' Button.
The Issue:
Currently I have implemented a AJAX function in the shared master layout.cshtml view that handles the click event of the search button, as shown:
$(document).ready(function () {
$(".searchBtn").click(function () {
var $searchTerm = $("#searchInput").val();
$.ajax({
url: '#Url.Action("ProductSearch", "Product")',
type: 'POST',
data: {
"searchTerm": $searchTerm,
"pageNumber": 0
},
success: function (result) {
window.location.href = result.url;
},
failure: function () {
alert('failed');
}
});
});
});
This is the ProductSearch method of the the Product Controller the AJAX call. The search term along with the page number is sent to the controller method:
public ActionResult ProductSearch(string searchTerm, int pageNumber)
{
if (searchId == 0)
{
searchId = 1;
}
var productDetailHandler = new ProductPageDBHandler(
new ProductDetailSqlServerHandler(new ProductDetailDataSetConvertor()));
var searchList = productDetailHandler.ProductSearch(searchTerm);
return View(searchList.ToPagedList(pageNumber, 3));
}
The problem is that this seems to not be returning the view I've associated with the ProductSearch method. How do I go about correctly redirecting to thw correct view once the user has submitted their search query?
Your ajax function is calling a method that returns a view. Change you success callback to
success: function (result) {
$('#someElement').html(result);
},
This will replace the contents of <div id="someElement"></div> with the returned view.

jQuery $.ajax() call is hanging and I cannot do nothing until the call ends

Hi;
when i'm using from jQuery ajax, the page getting to freeze until request end.
this is my JavaScript code:
function GetAboutContent(ID, from) {
var About = null;
if (from != true)
from = false;
$.ajax({
type: "POST",
url: "./ContentLoader.asmx/GetAboutContent",
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({ 'ID': ID, 'from': from }),
async: true,
success: function (msg) {
var Result = msg.d.Result;
if (Result == 'session') {
warning('Your session has expired, please login again!');
setTimeout(function () {
window.location.href = "Login.aspx";
}, 4000);
return;
}
if (Result == 'failed' || Result == false) {
About = false;
return;
}
About = JSON.parse(msg.d.About)[0];
}
});
return About;
}
and this is my WebService
[WebMethod(EnableSession = true)]
public object GetAboutContent(int ID, bool from = false)
{
try
{
if (HttpContext.Current.Session["MahdParent"] != null ||
HttpContext.Current.Session["MahdTeacher"] != null ||
from)
{
functions = new GlobalFunctions();
DataTable queryResult = new DataTable();
queryResult = functions.DoReaderTextCommand("SELECT Field FROM TT WHERE ID = " + ID);
if (queryResult.Rows.Count != 0)
return new { Result = true, About = JsonConvert.SerializeObject(queryResult.Rows[0].Table) };
else
return new { Result = false };
}
else
return new { Result = "session" };
}
catch (Exception ex)
{
return new { Result = "failed", Message = ex.Message };
}
}
How can i solve that problem?
please help me
In the last line you try to return About. That cannot work due to the asynchronous nature of an AJAX request. The point at which you state return About doesn't exist any more when the success function of your AJAX request runs.
I assume you try do do somehting like this:
$('div#content').html(GetAboutContent());
In a procedural lantuage like PHP or Perl this works fine, yet JavaScript functions in a very different way. To make something like this work you'd do something like this:
$.ajax({
type: "post",
url: "./ContentLoader.asmx/GetAboutContent",
dataType: "json",
data: {
'ID': ID,
'from': from
},
success: function(result) {
$('div#content').html(result)
}
});
The difference between the two bits of code is that the first would expect JavaScript to know the value at the time you request it. However, your function GetAboutContent() doesn't have instant access to these data. Instead it fires up an AJAX request and ends right after that with the request still in progress for an unknown amount of time.
Once the request finishes successfully the data is available to JavaScript. and you can work with it in the callback function defined for success. By then the request has absolutely no connection to the function that started it. That's why it's asynchronous.

.NET MVC JSON Post Call response does not hit complete or success

I am new to .NET MVC so please bear with me.
I wrote a function that gets triggered when there is a blur action on the textarea control:
function extractURLInfo(url) {
$.ajax({
url: "/Popup/Url",
type: "POST",
data: { url: url },
complete: function (data) {
alert(data);
},
success: function (data) {
alert(data);
},
async: true
})
.done(function (r) {
$("#url-extracts").html(r);
});
}
jQuery(document).ready(function ($) {
$("#input-post-url").blur(function () {
extractURLInfo(this.value);
});
});
This works fine and will hit the controller:
[HttpPost]
public ActionResult Url(string url)
{
UrlCrawler crawler = new UrlCrawler();
if (crawler.IsValidUrl(url))
{
MasterModel model = new MasterModel();
model.NewPostModel = new NewPostModel();
return PartialView("~/Views/Shared/Partials/_ModalURLPartial.cshtml", model);
}
else
{
return Json(new { valid = false, message = "This URL is not valid." }, JsonRequestBehavior.AllowGet);
}
}
I get the intended results if the URL is valid; it will return a partialview to the .done() function and I just display it in code. However, if the URL is not valid i want it to hit either complete, success, or done (I have been playing around to see which it will hit but no luck!) and do something with the returned data. I had it at some point trigger either complete or success but the data was 'undefined'. Can someone help me out on this?
Thanks!
In both cases your controller action is returning 200 status code, so it's gonna hit your success callback:
$.ajax({
url: "/Popup/Url",
type: "POST",
data: { url: url },
success: function (data) {
if (data.message) {
// Your controller action return a JSON result with an error message
// => display that message to the user
alert(data.message);
} else {
// Your controller action returned a text/html partial view
// => inject this partial to the desired portion of your DOM
$('#url-extracts').html(data);
}
}
});
But of course a much better and semantically correct approach is to set the proper status code when errors occur instead of just returning some 200 status code:
[HttpPost]
public ActionResult Url(string url)
{
UrlCrawler crawler = new UrlCrawler();
if (crawler.IsValidUrl(url))
{
MasterModel model = new MasterModel();
model.NewPostModel = new NewPostModel();
return PartialView("~/Views/Shared/Partials/_ModalURLPartial.cshtml", model);
}
else
{
Response.StatusCode = 400;
Response.TrySkipIisCustomErrors = true;
return Json(new { valid = false, message = "This URL is not valid." }, JsonRequestBehavior.AllowGet);
}
}
and then in your AJAX call you would handle those cases appropriately:
$.ajax({
url: "/Popup/Url",
type: "POST",
data: { url: url },
success: function (data) {
$('#url-extracts').html(data);
},
error: function(xhr) {
if (xhr.status == 400) {
// The server returned Bad Request status code
// => we could parse the JSON result
var data = JSON.parse(xhr.responseText);
// and display the error message to the user
alert(data.message);
}
}
});
Also don't forget that you have some standard way of returning your error messages you could subscribe to a global .ajaxError() handler in jQuery instead of placing this code in all your AJAX requests.

Categories

Resources