Cannot post to asp.net MVC controller - asp.net-mvc

Here is my request definition:
params = typeof params !== "undefined" ? params : {};
var deferred = $q.defer();
var response = $http({
method: "post",
dataType: "json",
data: JSON.stringify(params),
headers: {
'Content-Type': "application/json; charset=utf-8",
},
url: 'apiUrl' + 'MVCcontrollerName' + '/'
});
And C#:
public class MVCcontrollerName : Controller
{
public ActionResult Index(int? Id = null)
{
.......
I am not getting my Id parameter in the controller class. It's null. The parameter is defined as {Id:1}.
I also tested POST with Chrome REST client with the same results.
Any idea, what's wrong?

I see a couple of issues here.
First the name of your controller should follow the convention of SomenameController, so you might want to call it MVCcontrollerNameController
The URL you specify is missing a slash to delimit between the path and the controller name:
url: 'apiUrl' + '/' + 'MVCcontrollerName' + '/'
Or simply:
url: 'apiUrl/MVCcontrollerName/'
Or more correctly, let MVC do the routing for you (as suggested by #JamieRees):
url: '#Url.Action("Index","MVCcontrollerName")'
3. The main issue however, is that you are POSTing the data where you really should be calling it as a GET with the parameter as part of the URL. However, if you really need to have it in a POST, then you need to decorate the parameter with the FromBody attribute:
public ActionResult Index([FromBody]int? Id = null)

I'm not sure if this will help, but anyway you should have attribute [HttpPost] on action that will be called with post

Related

Controller in my MVC project returning null from Ajax Post call

I'm not sure to why the controller is receiving a data from an Ajax call . Could i be doing anything wrong?
[HttpPost]
[Route("Product/UpdateDetails")]
public ActionResult UpdateProduct (ProductModel model) <<// model here is null
{
Product p = new Product
{
ProductId = p.ProductId,
Price = p.Price,
};
return View("_ProductDetail"); }
Ajax call below:
var model = {
ProductId: 1,
Price: 270.99,
};
var json = JSON.stringify(model)
$.ajax({
url: '/Product/UpdateDetails',
type: 'Post',
contentType: "application/json; charset=utf-8",
model: model,
success: function (results) {
}
});
//Model
public class Product
{
public int Id {get;set;}
public double Price {get;set;}
}
Can you guys spot anything that i may be doing wrong in the code above ? I can't see anything that i'm doing wrong.
Try this:
$.ajax({
url: '/Product/UpdateDetails',
type: 'Post',
contentType: "application/json; charset=utf-8",
data: json,
success: function (results) {
}
});
You used JSON.Stringify() on your model, but forgot to use the variable "json" on the ajax call, so the ajax was trying to post a "non-json" model.
Also, there is no model setting in ajax calls, the correct one to post your data is data, as you can see here.

Can a web api post method contains more than one parameter?

I have this method in a controller in a web api
public class UserController : ApiController
{
[HttpPost]
public HttpResponseMessage Login(string name, string password){
//dothings
}
}
but if I try a ajax request:
$.ajax({
type: "POST",
url: "http://localhost:19860/Api/User/Login",
data: { name: "name", password: "12345" },
success: succ,
error: err
});
It gives me the error:
Message: "No HTTP resource was found that matches the request URI 'http://localhost:19860/Api/User/Login'."
MessageDetail: "No action was found on the controller 'User' that matches the request."
but, if i remove the parameters it works!
public class UserController : ApiController
{
[HttpPost]
public HttpResponseMessage Login(){
string name= HttpContext.Current.Request.Params["name"];
string password= HttpContext.Current.Request.Params["password"];
// name and password have the value that i passed in the ajax call!!
}
}
why it is like this?
For reasons unrelated to this question, I can't change the web api, so I have to mantain the:
public HttpResponseMessage Login(string name, string password)
format.
Can I mantain this format and be able to make the ajax call?
You can not post multiple parameter to Web-API methods as mentioned in this blog post
There is few alternative to this as follow.
1. Try to pass it on queryString.
Change your ajax function call like below.
$.ajax({
type: "POST",
url: "http://localhost:19860/Api/User/Login?name=name&pass=pass",
data: { name: "name", password: "12345" },
success: succ,
error: err
});
you will get name = name and password = pass in your api controller.
2. Create your own binder as implemented in this blog post.
3. Wrap all the Web-API method parameter in one object or type (recommended).
From the above you can use 1st and 2nd approach as you mentioned in your question you can not change your api method signature.

Web API - Multiple POST methods

I am writing a simple web api application. I came to a phase when I need to have two POST methods in my web api controller. One of these methods works and the other does not. My route table looks like this:
config.Routes.MapHttpRoute(
name: "ApiRouteWithAction",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Then I have my methods defined like this:
[HttpPost]
public bool PostTaskAgain(My3TasksWebAPI.Data.Task task)
{
var oldTask = _db.Task.Where(t => t.Id == task.Id).SingleOrDefault();
oldTask.DoAgain = true;
oldTask.DateUpdated = task.DateUpdated;
if (_db.SetOfTasks.Where(t => CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(t.DateCreated, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday) == CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(DateTime.Now, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday)).Any())
{
int currentSetOfTasksId = _db.SetOfTasks.OrderBy(s => s.DateCreated).FirstOrDefault().Id;
My3TasksWebAPI.Data.Task newTask = new Data.Task() { CreatedBy = oldTask.CreatedBy, DateCreated = oldTask.DateCreated, DateUpdated = null, DoAgain = false, Notes = string.Empty, SetOfTasksId = currentSetOfTasksId, Status = false, Title = oldTask.Title, UserId = oldTask.UserId };
_db.Task.Add(newTask);
}
_db.SaveChanges();
return true;
}
// Post api/values/PostSetOfTasks/{setOfTasks}
[HttpPost]
public bool PostSetOfTasks(My3TasksWebAPI.Data.SetOfTasks setOfTasks)
{
_db.SetOfTasks.Add(setOfTasks);
_db.SaveChanges();
return true;
}
When I try to call PostTaskAgain I get an internal server error. I think that it might be the routing table but I am not sure how to handle two post methods.
I call the web api from my asp.net mvc application like this:
HttpResponseMessage response = client.PostAsJsonAsync("api/values/PostSetOfTasks", model.SetOfTasks).Result;
and
HttpResponseMessage response = client.PostAsJsonAsync("api/values/PostTaskAgain", taskToPost).Result;
That means that I include the actions.
Working with POST in webapi can be tricky though conincidently, your issue turned out to be trivial. However, for those who may stumble upon this page:
I will focus specifically on POST as dealing with GET is trivial. I don't think many would be searching around for resolving an issue with GET with webapis. Anyways..
If your question is - In MVC Web Api, how to-
- Use custom action method names other than the generic HTTP verbs?
- Perform multiple posts?
- Post multiple simple types?
- Post complex types via jQuery?
Then the following solutions may help:
First, to use Custom Action Methods in Web API, add a web api route as:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}");
}
And they you may create action methods like:
[HttpPost]
public string TestMethod([FromBody]string value)
{
return "Hello from http post web api controller: " + value;
}
Now, fire the following jQuery from your browser console
$.ajax({
type: 'POST',
url: 'http://localhost:33649/api/TestApi/TestMethod',
data: {'':'hello'},
contentType: 'application/x-www-form-urlencoded',
dataType: 'json',
success: function(data){ console.log(data) }
});
Second, to perform multiple posts,
It is simple, create multiple action methods and decorate with the [HttpPost] attrib.
Use the [ActionName("MyAction")] to assign custom names, etc.
Will come to jQuery in the fourth point below
Third,
First of all, posting multiple SIMPLE types in a single action is not possible and there is a special format to post a single simple type (except for passing the parameter in the query string or REST style).
This was the point that had me banging my head with Rest Clients and hunting around the web for almost 5 hours and eventually, the following URL helped me. Will still quote the contents for the link may turn dead!
Content-Type: application/x-www-form-urlencoded
in the request header and add a = before the JSON statement:
={"Name":"Turbo Tina","Email":"na#Turbo.Tina"}
http://forums.asp.net/t/1883467.aspx?The+received+value+is+null+when+I+try+to+Post+to+my+Web+Api
Anyway, let us get over that story. Moving on:
Fourth, posting complex types via jQuery, ofcourse, $.ajax() is going to promptly come in the role:
Let us say the action method accepts a Person object which had an id and a name. So, from javascript:
var person = { PersonId:1, Name:"James" }
$.ajax({
type: 'POST',
url: 'http://mydomain/api/TestApi/TestMethod',
data: JSON.stringify(person),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function(data){ console.log(data) }
});
And the action will look like:
[HttpPost]
public string TestMethod(Person person)
{
return "Hello from http post web api controller: " + person.Name;
}
All of the above, worked for me!!
Cheers!
There was a problem with my LINQ query.
The response from the server was: {"$id":"1","Message":"An error has occurred.","ExceptionMessage":"LINQ to Entities does not recognize the method 'Int32 GetWeekOfYear(System.DateTime, System.Globalization.CalendarWeekRule, System.DayOfWeek)' method, and this method cannot be translated into a store expression.","ExceptionType":"System.NotSupportedException","StackTrace":" at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTransl‌​ator.Translate(ExpressionConverter parent, MethodCall....
After correcting the linq query everything is working fine. Visual studio was fine about me doing the linq query wrong.

asp.net mvc 3 json values not recieving at controller

the problem is that i am not able to recieve any value in the controller . what could be wrong? the code is here.
$('#save').click(function () {
var UserLoginViewModel = { UserName: $('vcr_UserName').val(),
Password: $('vcr_Password').val()
};
$.ajax({
url: "/User/Login",
data: JSON.stringify(UserLoginViewModel),
contenttype: "application/json; charset=utf-8",
success: function (mydata) {
$("#message").html("Login");
},
error: function () {
$("#message").html("error");
},
type: "POST",
datatype: "json"
});
return false;
});
});
[HttpPost]
public ActionResult Login(UserLoginViewModel UserLoginViewModel)
{
}
As you're using MVC3 - you should be able to take advantage of the built in JSON model binding.
Your code example has a couple of typos: contentType and dataType are lowercase...(they should have an uppercase "T")
jQuery ajax docs
After you POST up the correct contentType/dataType, MVC should automatically bind your object to the posted JSON.
You're going to need an action filter or similar to intercept the json from the post body.
Here's a starter
Provider Factory
but here is the article that sorted this for me On Haacked
It is good if you know the type you are deserialising into up front, but if you need polymorphism you'll end up using these ideas in an action filter.

MVC ajax json post to controller action method

I am trying to achieve a JQuery AJAX call to a controller action method that contains a complex object as a parameter.
I have read plenty blogs and tried several techniques learned from these. The key post on which I have constructed my best attempt code (below) is the stackoverflow post here .
I want to trigger an asynchronous post, invoked when the user tabs off a field [not a Form save post – as demonstrated in other examples I have found].
My intention is to:
Instantiate an object on the client [not the ViewModel which provides the type for the View];
Populate the object with data from several fields in the view;
Convert this object to JSON;
Call the controller action method using the jQuery.Ajax method, passing the JSON object.
The results will be returned as a JSON result; and data will be loaded into fields in the view depending on results returned.
The problems are:
If the action method is attributed with the HttpPost attribute, the controller Action method is not invoked (even though the AJAX call type is set to ‘POST’).
If the action method isattributed with HttpGet, the values of properties of the parameter are null
The ReadObject method throws the error: "Expecting element 'root' from namespace ''.. Encountered 'None' with name 'namespace'".
Hopefully someone can help. Thanks. Code below:
Client js file
var disputeKeyDataObj = {
"InvoiceNumber": "" + $.trim(this.value) + "",
"CustomerNumber": "" + $.trim($('#CustomerNumber').val()) + ""
};
var disputeKeyDataJSON = JSON.stringify(disputeHeadlineData);
$.ajax({
url: "/cnr/GetDataForInvoiceNumber",
type: "POST",
data: disputeKeyDataJSON,
dataType: 'json',
contentType: "application/json; charset=utf-8",
success: EnrichedDisputeKeyData(result)
});
Action Filter and class for the type associated with the Action method parameter
[DataContract]
public class DisputeKeyData
{
[DataMember(Name = "InvoiceNumber")]
public string InvoiceNumber { get; set; }
[DataMember(Name = "CustomerNumber")]
public string CustomerNumber { get; set; }
}
Action method on the controller
//[HttpPost]
[ObjectFilter(Param = "disputeKeyData", RootType = typeof(DisputeKeyData))]
public ActionResult GetDataForInvoiceNumber(DisputeKeyData disputeKeyData)
{
//Blah!
//....
return Json(disputeKeyData, JsonRequestBehavior.AllowGet);
}
Below is how I got this working.
The Key point was:
I needed to use the ViewModel associated with the view in order for the runtime to be able to resolve the object in the request.
[I know that that there is a way to bind an object other than the default ViewModel object but ended up simply populating the necessary properties for my needs as I could not get it to work]
[HttpPost]
public ActionResult GetDataForInvoiceNumber(MyViewModel myViewModel)
{
var invoiceNumberQueryResult = _viewModelBuilder.HydrateMyViewModelGivenInvoiceDetail(myViewModel.InvoiceNumber, myViewModel.SelectedCompanyCode);
return Json(invoiceNumberQueryResult, JsonRequestBehavior.DenyGet);
}
The JQuery script used to call this action method:
var requestData = {
InvoiceNumber: $.trim(this.value),
SelectedCompanyCode: $.trim($('#SelectedCompanyCode').val())
};
$.ajax({
url: '/en/myController/GetDataForInvoiceNumber',
type: 'POST',
data: JSON.stringify(requestData),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
error: function (xhr) {
alert('Error: ' + xhr.statusText);
},
success: function (result) {
CheckIfInvoiceFound(result);
},
async: true,
processData: false
});

Resources