WebAPIContrib
WebAPIContrib copied to clipboard
MvcActionValueBinder Execption in post
Hi, i have a problem in angular when send data in post method, in my client
this.prueba = function (id, nombre) {
return $http.post(ApiURL + "AEmpleado/prueba", { id: id, nombre: nombre })
.then(
function (respuesta) {
MensajeServices.MostarMensaje("", "Se elimino el Registro Correctamente", "success", null);
//vm.CargarTabla();
return respuesta
},
function (respuesta) {
console.log(respuesta.data.Message);
return false;
}
);
}
in my server
[RoutePrefix("api/AEmpleado")]
[MvcStyleBinding]
public class AEmpleadoController : ApiController
{
[HttpPost, Route("prueba")]
public IHttpActionResult prueba(int id, string nombre)
{
return Ok();
}
}
The error is:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Net.Http.Formatting.FormDataCollection' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'id', line 1, position 6.
in
private class MvcActionBinding : HttpActionBinding
{
// Read the body upfront , add as a ValueProvider
public override Task ExecuteBindingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
HttpRequestMessage request = actionContext.ControllerContext.Request;
HttpContent content = request.Content;
if (content != null)
{
FormDataCollection fd = content.ReadAsAsync<FormDataCollection>().Result;
if (fd != null)
{
IValueProvider vp = new NameValuePairsValueProvider(fd, CultureInfo.InvariantCulture);
request.Properties.Add(Key, vp);
}
}
return base.ExecuteBindingAsync(actionContext, cancellationToken);
}
}
anybody help? Sorry for my english
I see inconsistence: you're using [MvcStyleBinding]
or [MvcActionBinding]
or both ?
in the IHttpActionResult ? i'm use [MvcStyleBinding]
But the error occurs in private class MvcActionBinding
?
Yes, the complete class is:
public class MvcActionValueBinder : DefaultActionValueBinder
{
// Per-request storage, uses the Request.Properties bag. We need a unique key into the bag.
private const string Key = "{5DC187FB-BFA0-462A-AB93-9E8036871EC8}";
public override HttpActionBinding GetBinding(HttpActionDescriptor actionDescriptor)
{
var actionBinding = new MvcActionBinding();
HttpParameterDescriptor[] parameters = actionDescriptor.GetParameters().ToArray();
HttpParameterBinding[] binders = Array.ConvertAll(parameters, DetermineBinding);
actionBinding.ParameterBindings = binders;
return actionBinding;
}
private HttpParameterBinding DetermineBinding(HttpParameterDescriptor parameter)
{
HttpConfiguration config = parameter.Configuration;
var attr = new ModelBinderAttribute(); // use default settings
ModelBinderProvider provider = attr.GetModelBinderProvider(config);
IModelBinder binder = provider.GetBinder(config, parameter.ParameterType);
// Alternatively, we could put this ValueProviderFactory in the global config.
var vpfs = new List<ValueProviderFactory>(attr.GetValueProviderFactories(config)) { new BodyValueProviderFactory() };
return new ModelBinderParameterBinding(parameter, binder, vpfs);
}
// Derive from ActionBinding so that we have a chance to read the body once and then share that with all the parameters.
private class MvcActionBinding : HttpActionBinding
{
// Read the body upfront , add as a ValueProvider
public override Task ExecuteBindingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
{
HttpRequestMessage request = actionContext.ControllerContext.Request;
HttpContent content = request.Content;
if (content != null)
{
FormDataCollection fd = content.ReadAsAsync<FormDataCollection>().Result;
if (fd != null)
{
IValueProvider vp = new NameValuePairsValueProvider(fd, CultureInfo.InvariantCulture);
request.Properties.Add(Key, vp);
}
}
return base.ExecuteBindingAsync(actionContext, cancellationToken);
}
}
// Get a value provider over the body. This can be shared by all parameters.
// This gets the values computed in MvcActionBinding.
private class BodyValueProviderFactory : ValueProviderFactory
{
public override IValueProvider GetValueProvider(HttpActionContext actionContext)
{
object vp;
actionContext.Request.Properties.TryGetValue(Key, out vp);
return (IValueProvider)vp; // can be null
}
}
}
hello, i'm chage
FormDataCollection fd = content.ReadAsAsync<FormDataCollection>().Result;
for
var fd = content.ReadAsAsync<IDictionary<string, object>>().Result;
and it work but doesn't when send array :(
btw don't use Result
, use async/await
instead
when? in the content.ReadAsAsync<IDictionary<string, object>>().Result?
It's unrelated to the problem you're facing but yes, there and elsewhere, calling the Result property blocks current thread so you're not having async operation spite it looks like you will. If shortly, this is incorrect way to use it.
Regarding your problem, i frankly don't know, I'm not familiar with this part of the codebase. Please ask a question on Stack Overflow and provide a link to the question here, I'll assist if you're facing any issues there