In previous MVC5 and below, you could make an ajax call that unwrapped the parameters properly:
JS:
$.post('/controller/endpoint',{intparam: 1, strparam: 'hello'})
CS:
public ActionResult endpoint(int intparam, string strparam){}
In the new aspnetcore, it has changed:
CS:
public CustomClassWrapper{ public int intparam {get;set;} public string stringparam {get;set;} } public ActionResult endpoint([FromBody]CustomClassWrapper item){}
To sum it up, in the new framework, you need to write a wrapper class and can only pass one [FromBody] parameter to the method. Previously, the params would be unwrapped by variable name correctly.
So, i'm trying to re-implement this functionality in an aspnetcore middleware component. I'm having difficulty in how to accomplish calling the controller method properly with the parameters.
My current cut-down code:
public async Task Invoke(HttpContext context) { if (IsAjaxRequest(context.Request)) { try { string bodyContent = new StreamReader(context.Request.Body).ReadToEnd(); var parameters = JsonConvert.DeserializeObject(bodyContent); ///What to do here? } catch (Exception ex) { throw new Exception("AJAX method not found ", ex); } } else { await _next(context); } }
I'm really just not sure about what to do after deserializing the parameters. I have the URL for the endpoint and also the params correctly. Just need to know how to call the method and return the result as JSON. Should i be using Reflection to get the controller method? Or is there a better way using MVC?
2 Answers
Answers 1
it's very simple thing i don't know why it not working at your end
JS
$.post('actionMethodURl', { FirstName: '1', LastName: 'hello' }).done(Successfunction);
CS
[HttpPost] public ActionResult endpoint(string FirstName,string LastName) { object Message = string.Empty; if (ModelState.IsValid) { Message = "Pass"; } else { Message = ModelState.Errors(); } return Json(Message); }
Answers 2
Try implement custom IModelBinder.
public class BodyFieldModelBinder : IModelBinder { public Task BindModelAsync(ModelBindingContext bindingContext) { bindingContext.HttpContext.Request.EnableRewind(); // required to read request body multiple times var inputStream = bindingContext.HttpContext.Request.Body; if (inputStream.Position != 0L) inputStream.Position = 0; var bodyValue = new StreamReader(inputStream, Encoding.UTF8).ReadToEnd(); var jsonObject = (JObject)JsonConvert.DeserializeObject<object>(bodyValue); if (jsonObject.TryGetValue(bindingContext.FieldName, out var jToken)) { var jsonSerializer = JsonSerializer.Create(); var result = jToken.ToObject(bindingContext.ModelType, jsonSerializer); bindingContext.Result = ModelBindingResult.Success(result); return Task.CompletedTask; } bindingContext.Result = ModelBindingResult.Failed(); return Task.CompletedTask; } }
Be careful, the code above lacks error handling and etc.
And use it like this:
[HttpPost] public IActionResult Endpoint([ModelBinder(typeof(BodyFieldModelBinder))] int intparam)
Also you could implement custom attribute to reduce complexity of declaration:
public class BodyFieldAttribute : ModelBinderAttribute { public BodyFieldAttribute() : base(typeof(BodyFieldModelBinder)) { } }
0 comments:
Post a Comment