I am trying to send AJAX POST request to an MVC Application
$.ajax({
type: 'POST',
dataType: 'json',
data: {"FirstName":"chris","LastName":"cane"},
contentType: 'application/json',
url: "http://dev.irp.com/irp.Ajax.Search/home/Foo",
success: function (data) {
alert(data);
}
});
This script is present on a different server on an ASP.NET application. My MVC App to handle the code is as below
[HttpPost]
public JsonResult Foo(fromclient test)
{
var obj = new SearchMemberServiceClient();
var members = obj.FindMember(test.FirstName, test.LastName, "", "", "", "").Members;
IEnumerable<Bar> sorted =
from a in members
orderby a.FirstName ascending
group a by new
{
a.FormattedFullName,
a.MembershipsProxy[0].GoodFromDate,
a.MembershipsProxy[0].GoodThroughDate,
} into k
select new Bar
{
FormattedName = k.Key.FormattedFullName,
goodfrom = k.Key.GoodFromDate,
goodthru = k.Key.GoodThroughDate,
};
return Json(sorted.ToList());
}
public class Bar
{
public string FormattedName { get; set; }
public DateTime goodfrom { get; set; }
public DateTime goodthru { get; set; }
}
public class fromclient
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
The problem is the script needs to post to that url and get the json data. But as the controller does not have any view, When I look inside the console on the client side it says 404 error for the url and also it says XMLHttpRequest cannot load http://dev.irp.com/irp.Ajax.Search/home/Foo. Origin http://web-dev.irps.com is not allowed by Access-Control-Allow-Origin.
I dont know if the problem has to do with the absolute path of the url for ajax request. If so how could I overcome this?
Due to the same origin policy restriction that't built into browsers you cannot send AJAX requests to different domains. A possible workaround is to have the server return JSONP instead of JSON. Here's an example of a custom JsonpResult that you could use in your controller action.
Can U try JSONP ? Why json? It's perfect to cross-domain.
Related
I am developing mobile application using phonegap. I want to get information of user if user is already registered (i.e; records already available in database).On starting when user entered his unique id like Mobile Number and if he/she is already registered with this Mobile No then his/her full details will be shown to user on next page of mobile application
And I also want my application should be register with only one mobile number.
How it can be possible...plz Help me outThanks in advance,Nikhil Chavan
Use Ajax to send and recieve data,
function requestDataAtLogin(usermail, password, provider, id, version){
var dataO={
'Email':usermail,
'Pwd':password
};
var url="http://xxx.xxx.xx.xx/app.dev.web/MobileApp/api/Security/AuthenticateUser";
$.ajax({
type : "POST",
url : url,
data : JSON.stringify(dataO),
contentType : "application/json; charset=utf-8",
dataType : "json",
processData : true,
success : loginSuccess,
timeout: 50000,
error : loginFailed
});
}
}
function loginSuccess(data) {
alert("success");
}
function loginFailed(msg) {
alert("failed");
}
In the Web API service,
public MobileInitialDataModel AuthenticateUser(InitialRequestModel authenticationDetails)
{
//your service code
}
public class InitialRequestModel
{
public string Email { get; set; }
public string Pwd { get; set; }
}
public class MobileInitialDataModel
{
public byte[] Token { get; set; }
public string Status { get; set; }
public string Message { get; set; }
}
I have a UI that looks like this:
I am trying to data of the newly created row to the server so that the server may save it.
I am sending data in JSON format from the client to my MVC application. Here's my ajax request:
var values = []; // an array with each item being an object/associative array
// more code to get values into variables
for (var i = 0; i < cultures.length; i++) {
var cultureName = cultures[i];
var valueTextBox = $(row).find(...);
var value = $(valueTextBox).val();
var cultureNameAndValue = { 'CultureShortName' : cultureName, 'StringValue' : value };
values.push(cultureNameAndValue);
}
var stringTableRow =
{
'ResourceKeyId': resourceKeyId,
'Key': resourceKeyName,
'CategoryId': categoryId,
'CategoryName': categoryName,
'StringValues': values
};
var stringified = JSON.stringify({ StringTableRow: stringTableRow });
$.ajax('/Strings/JsonCreateNew',
{
cache: false,
async: false,
type: 'POST',
contentType: 'application/json; charset=UTF-8',
data: stringified,
dataType: 'json',
error: SaveNewResourceClientSideHandler.OnError,
success: SaveNewResourceClientSideHandler.OnSuccess
});
Here's the data it sends (as seen in Firebug):
{"StringTableRow":{"ResourceKeyId":"","Key":"Foo",
"CategoryId":"1","CategoryName":"JavaScript",
"StringValues":[
{"CultureShortName":"en-US","StringValue":"Something"},
{"CultureShortName":"fr-FR","StringValue":""}]
}}
Here's my server side code:
public ActionResult JsonCreateNew(StringTableRow row)
{
// CreateNewStringTableRow(row);
// return a success code, new resource key id, new category id
// return Json(
new { Success = true, ResourceKeyId = row.ResourceKeyId,
CategoryId = row.CategoryId },
JsonRequestBehavior.AllowGet);
return new EmptyResult();
}
And here's the business object that I want my incoming POST'ed data to be bound to:
public class StringTableRow
{
public StringTableRow()
{
StringValues = new List<CultureNameAndStringValue>();
}
public long ResourceKeyId { get; set; }
public string Key { get; set; }
public long CategoryId { get; set; }
public string CategoryName { get; set; }
public IList<CultureNameAndStringValue> StringValues { get; set; }
}
public class CultureNameAndStringValue
{
public string CultureShortName { get; set; }
public string StringValue { get; set; }
}
Global.asax
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
}
}
Problem:
The action JsonCreateNew receives an object that is not null but has all properties uninitialized, i.e all nullable properties are null and value properties are at their default values. Therefore, effectively I get no data at all even when the client sends a perfectly valid Json string.
Do I need to do custom model binding?
Okay, I solved my problem and this might be an important insight for other programmers as well, because I learnt something while solving my own problem.
My solution:
I resorted to not using JSON and instead used the default encoding that HTTP uses for encoding form posted values, and then I used something that smacks of custom model binding (without actually creating a model binder).
Explanation:
Normally, when you make an ajax request and pass data from the client to any server platform, if you do not specify the encoding, i.e. the contentType parameter in the settings object of jQuery's ajax method (or if you are using any other means to make the ajax request other than jQuery, then however that thing sets the ContentType HTTP header is what you're after), HTTP encodes your posted data using its default encoding, which is much like what you post with a GET request after the query string, only it is binary encoded and not sent as a part of the URL.
If that's the case, and you're posting a collection of any type (IList, IEnumerable, ICollection, IDictionary, etc.) to ASP.NET MVC, then don't create an associative array in JavaScript to embody the collection. Don't even create an array. Don't create anything.
In fact, just pass it along inside the main big object using the convention:
data =
{ /*scalar property */ Gar: 'har',
/* collection */ 'Foo[index++].Bar' : 'value1',
'Foo[index++].Bar' : 'value2'
}
And don't use JSON. That will solve half your problem.
On the server side, receive the posted data in a FormCollection and use its IValueProvider methods (GetValue) to dig out the data you need. You don't have to explicitly create a model binder to do it. You can do it in a private method of your controller itself.
I will improve this answer a bit later when I can find more time.
Use Backbone or KnockoutJs for data binding.
I have an MVC view model that looks like this:
public class DirectorySearchModel
{
[Display(Name = "First name contains")]
public string FirstName { get; set; }
[Display(Name = "Last name contains")]
public string LastName { get; set; }
public CountriesCollection Countries { get; set; }
public IEnumerable<Country> SelectedCountries { get; set; }
public IEnumerable<Country> AllCountries { get; set; }
}
The CountriesCollection object (line 9) looks like this:
public class CountriesCollection
{
[Display(Name = "Countries")]
public int[] arrCountries { get; set; }
}
Now, I'm creating a new, blank instance of CountriesCollection and then adding it to a blank instance of the DirectorySearchModel view model and then serialising it all into a javascript view model for Knockout.js:
{
"FirstName":null,
"LastName":null,
"Countries":{"arrCountries":[]},
"SelectedCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}],
"AllCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}]
}
My checkboxes are rendered as: <input checked="checked" data-bind="checked: Countries.arrCountries" id="Countries_arrCountries30" name="Countries.arrCountries" type="checkbox" value="1">. Checking a couple means you end up with this Knockout.js view model:
{
"FirstName":null,
"LastName":null,
"Countries":{"arrCountries":["1", "3"]},
"SelectedCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}],
"AllCountries":[{"RelationshipManager":{},"CountryId":1,"CountryName":"UK"},{"RelationshipManager":{},"CountryId":2,"CountryName":"France"},{"RelationshipManager":{},"CountryId":3,"CountryName":"Spain"}]
}
Submitting my view normally (i.e. via a submit button and not with Knockout.js) to an MVC action that expects a DirectorySearchModel, I'm able to ask for model.Countries.arrCountries to get a list of the checked items, but when I use...
$.post("/MyController/MyAction", ko.toJS(viewModel), function(returnData) {
$("#resultCount").html(returnData);
});
or...
$.post("/MyController/MyAction", viewModel, function(returnData) {
$("#resultCount").html(returnData);
});
to another action that expects the same DirectorySearchModel, model.Countries.arrCountries is always null! I wondered if it's due to Knockout.js posting the arrCountries entries as string[]s when MVC is expecting int[]s, but changing my MVC code to expect string[]s doesn't seem to change much..! The CountriesCollection object within the DirectorySearchModel appears to exist, but it's the arrCountries within that's always null.
Any ideas? Any help much appreciated!
Edit
The action that receives the Knockout.js viewModel:
public MvcHtmlString ResultCount(DirectorySearchModel model)
{
return new MvcHtmlString(getResultCount(model).ToString());
}
The getResultCount method:
public int getResultCount(DirectorySearchModel model)
{
IUserRepository userRepository = new UserRepository();
int count = userRepository.Search(model, null).Count();
return count;
}
FIXED!
Thanks to Konstantin for pointing out that a simple switch from $.post to $.ajax to send my Knockout.js view model back to my mvc action was all that was needed! Here's the $.ajax code I'm using:
$.ajax({
type: "POST",
url: "/MyController/MyAction",
data: ko.toJSON(viewModel),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
$("#resultCount").html(data);
}
});
You cant use $.post you need to go for the underlying $.ajax and add the correct contenttype to make mvc accept the posted json and do the model binding (contenttype should be "application/json; charset=utf-8") google for it and you will se lots of examples
I have 3 classes with below definition
public class UserRole
{
public User User { get; set; }
public IEnumerable<Role> Role { get; set; }
}
public class Role
{
public int Id{ get; set; }
public string RoleName{ get; set; }
}
public class User
{
public int Id{ get; set; }
public string UserName{ get; set; }
}
This is the action method:
// GET: /Admin/UserManagement/Create
[HttpPost]
[Transaction]
public ActionResult Save(UserRole userrole)
{
}
Is there a way in Jquery to serialize some JavaScript vars into a class Obj and then send it to an MVC controller action via an AJAX post?
You could send a JSON request:
var data = {
user: {
id: 5,
userName: 'john'
},
role : [
{ id: 1, roleName: 'role 1' },
{ id: 2, roleName: 'role 2' },
{ id: 3, roleName: 'role 3' }
]
};
$.ajax({
url: '#Url.Action("Save")',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(data),
success: function(result) {
alert('success');
}
});
The JSON.stringify method is natively built into modern browsers but if you need to support legacy browsers you could include the json2.js script.
The easiest way to do it out-of-the box with all the parts happy (jQuery, MVC Framework) is to serialize the object graph as JSON data on the client and pass that into the POST. The MVC Framework is actually quite good at sorting the model binding out for you.
There is a downloadable sample with a similar complex object here:
http://theycallmemrjames.blogspot.ca/2010/05/aspnet-mvc-and-jquery-part-4-advanced.html
It deals with model binding in a number of different scenarios. Check out the suitcase example for your needs. Disclaimer: It's my blog, hope that doesn't offend.
Cheers.
I've seen other posts on this subject and have fiddled with variations but still cannot not get the JSON model binding to work correctly.
I have the following in my global.asax.cs Application_Start method:
ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
The post back data looks like this:
{"UserName":"Mike","Password":"password","Persist":true}
My PoCo:
public class UserLoginViewModel {
public string UserName { get; set; }
public string Password { get; set; }
public bool Persist { get; set; }
}
The controller method fires properly but has default UserLoginViewModel object with UserName = null, Password = null, and Persist = false; the signature looks like this:
[HttpPost]
public ActionResult Logon(UserLoginViewModel model) {
if (ModelState.IsValid) {
...
The problem is on the client side! I didn't have the contentType set.
$.ajax({
url: location.href,
type: "POST",
data: ko.toJSON(this),
datatype: "json",
**contentType: "application/json charset=utf-8",**
success: function (data) { alert("success"); },
error: function (data) { alert("error"); }
});