I have a web application that uses VB.NET MVC for the server side code. I set up the client side JavaScript to easily send and receive data to the server Controller functions. Basically what I did was create a JavaScript "request" object that uses Ajax to call a controller function and pass in parameters. I let MVC do all of the serialization for me. Then the controller function returns a JSON, usually with a block of HTML as a string. Since I am handling all of the ajax calls in one place, I can't figure out a good way to handle the responses. When the ajax response comes back, I have no way of knowing which request it came from. The website has a lot going on so the responses all need to be handled differently and all return different data.
Right now what I do is in the controller function I send back some key along with the block of HTML, then in the ajax complete function I check for all of these specific keys. Doing it this way makes the javascript code difficult to manage.
var postData = { id=0 };
$.ajax({
type: "POST",
url: "/Controller/Action/"
data: postData
}).done(function (data) {
if (data.Foo) {
Foo(data);
} else if(data.Bar) }
Bar(data);
}
});
I am having trouble researching this because I don't know which keywords to look up. I think I'm going to try and do something where I call the function names dynamically in the ajax done function, but I was wondering if there are any existing libraries or code examples that do larger scale ajax request functions like this.
Maybe the problem comes from the idea of "doing all the stuff in one place". I can imagine that it will be very difficult to maintain your code once you have 40 chained if...else if... in one method. Maybe splitting things up a bit wont hurt after all.
Anyway, one way of doing it the way you want it would be instead of passing a key, passing the name of the javascript function as a delegate. Then call window[data.funcName](data); in done().
Say your json is
{
foo: "bar",
funcName: "DoMyFoo"
}
This is how your call would look like :
var postData = { id=0 };
$.ajax({
type: "POST",
url: "/Controller/Action/"
data: postData
}).done(function (data) {
window[data.funcName](data);
});
function DoMyFoo(d){
//Do your specific stuff here
alert(d.foo);
}
See this question How to execute a JavaScript function when I have its name as a string for info and examples.
Edit: If your functions lies within an object instance instead of the global namespace, say obj, you can call it the same way with obj['myFunction'](args)
Related
I have a side bar currently in ul and li elements seen in the picture below.
And I have three charts on the right side of it.
Each chart has its own REST web-service to update its data.
When I click on the side bar items I want to update those charts. (Through Ajax calls)
What is the high-level design for this? For example do I need link_to on my li elements? What to put in there? How to pass params? How to make the calls? Any gems that makes the life easier?
Some high-level and even lower level design is appreciated so I know where to begin from.
This is more an AJAX question than a rails question.
You need to add click handlers on the li's (jQuery is probably the easiest way to go) and have those send an AJAX request to your REST endpoints for the charts. Depending on your setup, I would recommend having those endpoints return the data you're looking for in JSON format and then updating the values in the charts (maybe go crazy and use d3js to draw them).
I'm guessing the REST endpoints need a physician_id or something in order for them to return the correct data, and you'll need to get this from somewhere. I usually just add the id as a data attribute on the element.
<li class="js-physician" data-id="<%= physician.id %>">Physician X</li>
I'm assuming you're iterating over a #physicians collection to get the list.
Then for your js do something like
$(document).on('click', '.js-physician', function(e) {
var physician_id = e.target.getAttribute('data-id');
params = { // this is your AJAX object
type: 'GET',
url: '/some_rest_url?physician_id=' + physician_id,
success: function(data) {
// update the charts with the returned data
},
error: function(jqXHR, textStatus, errorThrown) {
// handle error
}
};
$.ajax(params);
});
so all you have to do then is set up your callback handlers and make sure you're sending the right data.
I am using the Kendo UI grid in my MVC3 application and am quite pleased with it. I am using a Telerik provided example, excerpt below, to format the data posted by the grid's DataSource ally, and all is good. However, I don't want to have to rely on code like this. I would like to get Kendo and MVC talking without the 'translator', i.e. this code:
parameterMap: function(data, operation) {
var result = { };
for (var i = 0; i < data.models.length; i++) {
var model = data.models[i];
for (var member in model) {
result["models[" + i + "]." + member] = model[member];
}
}
return result;
}
This function is a 'hook' that allows me to manipulated data before Kendo ajaxes it out. By default, the Kendo DataSource sends content-type form-encoded, but not quite right for the MVC model binder. Without this, I can still use a FormCollection and do my own binding, but that is not on.
When I configure the DataSource to send JSON, and change my mapping function to look like this
parameterMap: function(data, operation) {
return JSON.stringify(data);
}
I get the following data being send in the request, but now I have no idea how to get MVC to bind to this. Right now my only hope is to grab Request.Params[0] in the action method, and deserialize this JSON myself.
I don't think I should have to write any code to get two HTTP endpoints to communicate properly using JSON in this day and age. What am I doing wrong, or, what should I be looking at on my side, i.e. the receiver of the requests. I would really prefer to minimize my intervention on the client side to maybe just the stringify call.
No idea if this is still a problem or not since this is a rather old question, but I had a scenario where I was shipping up json data to my controller and I had to give it a "hint" on what the name was so that model binding would work correctly:
public JsonResult GetDatByIds([Bind(Prefix="idList[]")]List<Guid> idList)
In my scenario, kendo was serializing my data and giving it a name of idList[] in the form post rather than just idList. Once I gave it the model binding hint, it worked like a charm. This might be the same for your scenario.
I have an ajax POST request that is supposed to be submitting data to an ASP.NET MVC action. This works fine 95% of the time but every so often, for whatever reason, my FormCollection is empty and the application errors out as a result.
I would have included the raw request values however I haven't been able to reproduce this myself.
My ajax call looks like this:
var data = {};
data.Property = 123; // etc
$.ajax({
url: url,
type: 'POST',
dataType: 'json',
data: JSON.stringify(data),
success: function(viewModel) {
// do stuff
}
});
What would cause the FormCollection to intermittently be empty on the ajax POST?
I have suspected things like session timeouts and the like but I would expect that to error out before I get in to the action.
First of all you seem to be sending a JSON request (JSON.stringify(data)). This is not supported out of the box in ASP.NET MVC 2. It is in ASP.NET MVC 3 that a JsonValueProviderFactory was introduced. You may take a look at the following article which explains in more details JSON requests in ASP.NET MVC.
Also everytime you want to send a JSON request you should set the proper content type using the contentType parameter:
data: JSON.stringify(data),
contentType: 'application/json; charset=utf-8',
and last but not least I would recommend you to use view models instead of relying on some weakly typed structures such as FormCollection in your controller actions and having to write plumbing code.
UPDATE:
FormCollection is a key/value pair collection. So if you want to use it (despite my recommendation against it) you should not use a JSON request. You should use a normal key value request. So remove the JSON.stringify from your AJAX request and remove the contentType: 'application/json' parameter as well. There's really no point in using weakly typed key/value pair collection with JSON objects.
I inherited an MVC app and am a true novice at it coming from an ASP.NET environment. My problem is I can't manage to move variable data between my partial views and controllers. In ASP.NET this was pretty straight forward, not the case in MVC. So the following code fires when a Tab is selected from the client but I need to capture the selectedTabIndex value from the client and pass it to the controller.
function onTabSelect(e) {
var selectedTabIndex = 0;
selectedTabIndex = $(e.item).index();
alert(selectedTabIndex);
}
I considered using the ViewData object but there doesn't appear to be a way to make perform this task of assignment from within the function. So the following code would seem to be a ridiculous task and it fails anyway. (Remember, I am an extreme novice at this)
function onTabSelect(e) {
var selectedTabIndex = 0;
<% =ViewData["selectedTabIndex"]%> = selectedTabIndex;
}
I also considered using cookies but that doesn't seem to be a practical method either. In ASP.NET I could access the client controls using the .find method but this is a steep learning curve for me.
What are my alternatives?
If different tabs can be selected by the user between Save operations, you might need to consider binding some kind of click function (using jQuery) to set the selectedTabIndex javascript variable. Alternatively, you could set a hidden input's value to the selected tab index.
In either case, if you need the value in your controller (to set ViewData, ViewBag, some model data, etc) when a Save operation is submitted, you could submit the data via $.ajax and return some JSON from your controller
$('#SaveButton').click(function() {
$.ajax({
url: '/Controller/Save',
type: 'POST',
// you might need to serialize additional data you want to save here
// but you could create any JSON object before calling $.ajax
data: {"selectedTabIndex": selectedTabIndex}, // data to POST
dataType: 'json', // this indicates the type of data returned from controller
success: function(data) {
// you didn't really describe how to programatically set a tab,
// so "setToTab" is a guess
$('#tabID').setToTab(data.selectedTabIndex);
}
});
}
And your controller might look something like
public ActionResult Save(int selectedTabIndex)
{
// again, you might need different parameters to complete your Save
return JsonResult(new { selectedTabIndex: selectedTabIndex });
}
Data is sent to a controller via a HTTP POST. Create a hidden input <input type="hidden" name="selectedTabIndex"/> and set the value with javascript prior to POST. The controller can extract this value from the Form parameters, or it can be autopopulated in the Action method if the method contains a parameter matching the input name.
This is a non-ajax alternative to the answer provided by David.
I have no problems processing jQuery GET requests in a controller, however I cannot get any form data to POST. The client snippet
$.post(url,{name:"John"},function(result){
//process result
});
combined with a controller,
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Save(string name)
{
return Json("Success!");
}
will result in a NULL value for the name parameter when inspected inside the action method, whereas I expected name to be mapped to the method parameter. Also all other objects (Request.Form), etc. in this context seem to be NULL. I can do this with a $.get, but I think I am supposed to do any operations with side-effects with POSTs. I am using ASP.NET MVC 1.0, jQuery 1.2.6 and Internet Explorer 7.
Thanks!
Update: see my answer below and humble apologies
Sorry guys, I had a $.ajaxSetup entry in the page which overrided the default contentType to application/json.
When using the default contentType as follows:
$.ajax({ url,
type: "POST",
contentType: "application/x-www-form-urlencoded",
success: function(result) { alert(result); },
data: { name: "John" }
});
It works because processData is true by default which means the data entry with the JSON object will be parsed into a string (data: "name=John" also works).
Sorry for wasting your time :) and thanks to Mark for the suggestion on passing JSON objects, ill do that next cause it seems very cool.
I believe your code should work, is your URL correct and your routes setup correctly? In addition you could always fire up Fiddler to see exactly what your request to the server is and if you are passing the correct items.
Could it be that the Save(string name) method is expecting stringified JSON? Try this:
$.post(url,
"{'name':'John'}", function(result){
});
It isn't so simple as making a json object and throwing it at an action.
Start from here. People have written small scripts that get the JSON object dressed and ready for an action to read it in and map it to properties or arguments.