Request ambiguos between the following action methods Create - c#

I have looked at the solutions on the site. i have created two methods one for [HttpPost] and another for [HttpGet] as shown but still i am getting that error message. The code is as shown. but when i make a post request to the server i still get the error.
[HttpGet]
public ActionResult Create()
{
return View();
}
[HttpPost]
public String Create(Customer Customer)
{
/// logic here
return "Done";
}
The current request for action 'Create' on controller type '******Controller' is ambiguous between the following action methods:
System.String Create(Data.Models.***) on type Data.Controllers.UserController
System.Web.Mvc.ActionResult Create(System.Web.Mvc.FormCollection) on type Data.Controllers.UserController i am calling the method from a javascript code as shown below that is when I get the error message.
$.ajax({
url: urlPath + '/Create',
type: 'post',
dataType: 'json',
data: ko.toJSON(this),
contentType: 'application/json',
success: function (result) {
window.location.href = urlPath + '/';
}

Check your error message. These methods are OK as they are. But you have another Create method with FormCollection parameter: Create(System.Web.Mvc.FormCollection). If you don't have that method anymore, maybe you forgot to build your project?

Related

Send List items using JQuery Post to ASP.NET Controller

I have the following JQuery code in my .cshtml file.
$.ajax({
type: "POST",
url: urlPath,
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify({ pendingList: pendingList })
}).error(function (err) {
alert("Error " + err.status);
});
The pendingList object populates with correct values.I could see the values in the post request.
Request Data View
My ASP.NET Controller
[HttpPost]
public ActionResult CreateMultiRequest(List[] pendingList)
{
But I see null for the pendingList.Any help appreciated.
You're posting JSON that looks like:
"pendingList": {
//...
}
Thus, .Net is trying to bind the posted data to an object shaped like:
class SomeType
{
public List[] SomeOtherType { get; set; }
}
Instead, just call JSON.stringify(pendingList) which will send:
{
//...
}
You don't need to send a named object to the ASP .Net controller. It already expects the format of the object to match the type of parameter in the controller method.
There are two ways to fix this.
One:
Just like suggested in other answers use a generic list of type
[HttpPost]
public ActionResult CreateMultiRequest(List<PnedingList> pendingList)
Two:
Use FromBody attribute to help the runtime to retrieve the object from request body
[HttpPost]
public ActionResult CreateMultiRequest([FromBody]List[] pendingList)

.Net Core Binding

I am using .Net Core 2.1. This is the function that takes the value of the input boxName from the user and is supposed to pass it to the controller - Create function when the "save button" is clicked.
<script type="text/javascript">
function Submit() {
var boxName = $("#boxID").val();
alert(boxName);
UNTIL HERE EVERYTHING IS FINE - THE ALERT RETURNS THE CORRECT VALUE
$.ajax({
type: "POST",
contentType: "application/json",
url: '/Box/Create',
datatype: 'json',
data: JSON.stringify({ ID: "#Model.Id", BoxName: boxName }),
success: function (response) {
alert("Box created");
}
error: function (response) {
alert("error");
}
});
}
IN THE CONTROLLER
public ActionResult Create(int ID, string BoxName)
{
Box _Box = new Box();
_Box.Name= BoxName;
_db.Boxes.Add(_Box);
_db.SaveChanges();
return RedirectToAction("Index");
}
THE STRING BoxName RECEIVED AS A PARAMETER FROM THE AJAX IS NULL
I even tried
public ActionResult Create([Bind(Include = "ID,BoxName")] Box Box)
but it didn't work either. The error was
Include is not a valid named attribute argument
Any help is appreciated.
Remove the content Type and don't use stringify. So your ajax call becomes
$.ajax({
type: "POST",
url: '/Box/Create',
datatype: 'json',
data: { ID: "#Model.Id", BoxName: boxName },
success: function (response) {
alert("Box created");
}
Edit: This is partially wrong though you should do it for clarity. If there is only one action and the verb is not specified in your controller, the action is done anyway regardless if it's POST or GET.
You are using a POST verb in your ajax, by default all actions in the controller are GET. Add the [HttpPost] attribute above your controller action.
[HttpPost]
public ActionResult Create(int ID, string BoxName)
{
...
}
You should create a binding from the body of the request : ie:
class CreateBinding {
public string ID { get; set;}
public string BoxName { get; set; }
}
And in you controller:
[HttpPost]
Public ActionResult Create([FromBody] CreateBinding binding)
{
var id = binding.ID;
var name = binding.BoxName;
....
}

I can't pass more than one parameter to ASP Web API

I tried to pass more than one parameter from client-side using jQuery to ASP Web API method, but the method can't accept that. I tried some of the solutions but the same thing.
Web API:
[HttpPost]
[ResponseType(typeof(Message))]
[Route("api/Messages/send-message")]
public async Task<IHttpActionResult> SendMessage(Email email, Message message){}
jQuery:
$.ajax({
url: '/api/Messages/send-message',
method: 'POST',
contentType: "application/json; charset=utf-8",
dataType: "json",
data: JSON.stringify({
email: EmailsArray,
title: $('#txtTitle').val(),
body: $('#txtContent').val(),
}),
success: function (response) {
console.log(response);
});
Error Message:
"message":"An error has occurred.","exceptionMessage":"Can't bind multiple parameters ('email' and 'message') to the request's content.","exceptionType":"System.InvalidOperationException"
If you're sending the data as JSON then all the data needs to be contained in a single coherent JSON structure. Having two separate input parameters on the server side does not fit with this concept.
In this situation you can create a DTO (Data Transfer Object) which is a class holding all of the items you want to transfer. Something like this:
public class EmailMessageDTO
{
public Email email { get; set; }
public Message message { get; set; }
}
Then you define the action method as accepting this single over-arching object
public async Task<IHttpActionResult> SendMessage(EmailMessageDTO dto) { }
And in the JavaScript:
data: JSON.stringify({
email: EmailsArray,
message: {
"title": $('#txtTitle').val(),
"body": $('#txtContent').val(),
}
}),
It's quite similar to the concept of having a ViewModel in MVC.
You need to add [FromBody] attribute to parameter and you need to make post data to application/x-www-form-urlencoded and you send only email parameter, you need to add message parameter if you wanna send title and body you need to create model like
model:
public class EmailSendModel(){
public string email{get;set;}
public string title{get;set;}
public string body{get;set;}
}
controller:
[HttpPost]
[ResponseType(typeof(Message))]
[Route("api/Messages/send-message")]
public async Task<IHttpActionResult> SendMessage([FromBody]EmailSendModel model){}

Why does changing controller's parameter provoke http Post 404 error?

I am developing an Azure Web app with a database. I've a model and controller for the database. I'm trying to Post data on the database, but have some trouble understanding why does this code send a 404 error when sending data from the Web-Client to the controller.
Here is how I send the data in AngularJS (parameter is a Json string):
$http({
method: 'post',
url: serviceBasePath + "/api/suscribe",
data: parameter,
headers: { 'Content-Type': 'application/json' }
}).then(function (response) {
userService.SetCurrentUser(response.data);
defer.resolve(response.data);
}, function (error) {
defer.reject(error.data);
})
On the controller side, I get 404 if the controller is :
[HttpPost]
[Route("api/suscribe")]
public IHttpActionResult PostGTW_Utilisateur(String JsonString)
{
//
}
But if I leave the model as a parameter, the 404 error is gone :
[HttpPost]
[Route("api/suscribe")]
public IHttpActionResult PostGTW_Utilisateur(User u)
{
//
}
Json object class :
public class JsonSuscribeModel
{
public Utilisateur user { get; set; }
public string guid { get; set; }
public string password2 { get; set; }
}
You miss the endpoint since it does not know what JsonString is. You sent a JSON but in the controller model, you told it to listen for string. Open up Chrome (or other) dev tools and see EXACTLY what you are sending with the request.
Here is another tip:
$http({
method: 'post',
url: serviceBasePath + "/api/suscribe",
data: parameter,
headers: { 'Content-Type': 'application/json' }
}).then(function (response) {
userService.SetCurrentUser(response.data);
defer.resolve(response.data);
}, function (error) {
defer.reject(error.data);
})
I have seen the misuse of promises SO many times. Why would you use $http (which is itself a promise) and then process it in service and return ANOTHER promise? You can simply return $http (and resolve its promises in a controller. You are gonna have to resolve this new promises you are returning anyway, so why have an extra step.
return $http({
method: 'post',
url: serviceBasePath + "/api/suscribe",
data: parameter,
headers: { 'Content-Type': 'application/json' }
}).then(function (response) {
userService.SetCurrentUser(response.data);
return response.data;
}, function (error) {
return error.data;
})
This way you return entire $http and you instruct it what to return in success and error. Since itself it's a promise it will behave same as before.
Thanks for the tips.
The solution was to use the JsonModel I had as a parameter :
public IHttpActionResult PostGTW_Utilisateur(JsonSuscribeModel JsonModel)

"Incorrect Content-Type: " exception throws angular mvc 6 application

I'm developing an application using asp.net, mvc6 and angularjs on my angular service. When I make a request to an action method, I get no passed data.
When I have checked the request, I could see an exception that caused by:
Form '((Microsoft.AspNet.Http.Internal.DefaultHttpRequest)this.Request).Form'
threw an exception of type
'System.InvalidOperationException' Microsoft.AspNet.Http.IFormCollection
{System.InvalidOperationException}
exception message saying "Incorrect Content-Type:application/json;charset=UTF-8"
my angular service
return $http({ method: 'POST', url: 'home/createEvent', eventDetails: event })
.success(function(data, status, headers, config) {
return data;
})
.catch(function(data, status, headers, config) {
console.log(data);
});
on my controller
[HttpPost]
public IActionResult CreateEvent([FromBody]Event eventDetails)
{
return Json(new {dsd=""},
new JsonSerializerSettings {ContractResolver = new CamelCasePropertyNamesContractResolver()});
}
The accepted answer didn't work for me. For me, the solution was to add a header to the $http call:
$http({
url: "/install",
method: "POST",
data: data,
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
})
.success(...);
Hope the following examples helps you.
Try to decorate your controller with
[Produces("application/json")]
[Route("api/[controller]")]
Since you din't show your controller name I will give you a fictitious full working example
controller
[Produces("application/json")]
[Route("api/[controller]")]
public class DashBoardLayoutApi : Controller
{
public DashBoardLayoutApi()
{ }
[HttpPost]
public void Post([FromBody] LoginViewModel data)
{ }
}
C# viewmodel
public class LoginViewModel
{
public string Email { get; set; }
public string Password { get; set; }
}
HTML/JS
<script>
var data = {
Email: 'Test',
Password: 'Test',
RememberMe: true
};
$("#test").click(function() {
$.ajax({
url: '/api/DashBoardLayoutApi',
type: 'POST',
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(data),
});
}
</script>
<button id="test"> Save Layout</button>
Results
In my case, adding [Produces("application/json")] did nothing, but adding the [FromBody] attribute to the parameter is what did the trick!
The hidden's answer is great. However, I still had empty model in C# controller, even after I implemented hidden's approach in my application. After digging around a bit I found that the issue was in incorrect client model created in JS code, which cannot be deserialized on the server (null can not be converted to type Guid).
For some reason, model binder does not throw exceptions in such cases:
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding
When a parameter is bound, model binding stops looking for values with that name and it moves on to bind the next parameter. If binding fails, MVC does not throw an error. You can query for model state errors by checking the ModelState.IsValid property.
So, check the ModelState.IsValid property in C# controller to make sure you passed valid model and maybe consider using custom model binder to catch model binding errors and log them.

Categories