将ASP.NET Core的AJAX处理恢复到以前的功能

时间:2018-06-11 18:10:19

标签: asp.net-core asp.net-core-mvc

在之前的MVC5及以下版本中,您可以进行正确打开参数的ajax调用:

JS:

$.post('/controller/endpoint',{intparam: 1, strparam: 'hello'})

CS:

public ActionResult endpoint(int intparam, string strparam){}

在新的aspnetcore中,它发生了变化:

CS:

public CustomClassWrapper{ 
    public int intparam {get;set;}
    public string stringparam {get;set;}
}
public ActionResult endpoint([FromBody]CustomClassWrapper item){}

总而言之,在新框架中,您需要编写一个包装类,并且只能将一个[FromBody]参数传递给该方法。以前,params将被变量名称正确打开。

因此,我试图在aspnetcore中间件组件中重新实现此功能。我在如何使用参数正确调用控制器方法方面遇到了困难。

我目前的缩减代码:

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);
            }
        }

我真的不确定反序列化参数后要做什么。我有正确的端点和params的URL。只需要知道如何调用该方法并将结果作为JSON返回。我应该使用Reflection来获取控制器方法吗?或者有更好的方法使用MVC吗?

2 个答案:

答案 0 :(得分:1)

尝试实现自定义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;
    }
}

请注意,上面的代码缺少错误处理等。

并像这样使用它:

[HttpPost]
public IActionResult Endpoint([ModelBinder(typeof(BodyFieldModelBinder))] int intparam)

您还可以实现自定义属性以减少声明的复杂性:

public class BodyFieldAttribute : ModelBinderAttribute
{
    public BodyFieldAttribute()
        : base(typeof(BodyFieldModelBinder))
    {
    }
}

答案 1 :(得分:0)

这很简单,我不知道为什么它在您的末端不起作用

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);
}

MyJSCode MyActionMetho