ASP.NET Core MVC Ajax发布到具有多个参数的控制器返回错误的请求

时间:2018-11-29 10:53:27

标签: c# asp.net-core asp.net-core-2.1

我的控制器操作方法如下,

WebDriver

public class UserController : BaseController<UserController> { [HttpGet] public IActionResult Assignment(Guid id) { return View(); } [HttpPost] public IActionResult Assignment(Guid id, [FromBody] List<UserViewModel> assignees) { return View(); } } 页中的ajax方法

Assignment.cshtml

所以这会建立一个类似的网址

  

$("#btn-save").click(function () { var url = "/User/Assignment/@Model.SelectedUser.Id"; $.ajax({ type: "POST", url: url, contentType: "application/json", data: JSON.stringify({ assignees: assignmentPage.SelectedUsers }) }); });

这是我的http://localhost:8800/User/Assignment/f474fd0c-69cf-47eb-7281-08d6536da99f中唯一的路由配置。

Startup.cs

我从没执行过“ 发布”操作,服务器返回了“ 400 ”,我已经搜索并且找不到,我应该如何为这样的动作?

2 个答案:

答案 0 :(得分:1)

您要发送到服务器的数据是无效。它期待一个JSON数组,但是您要向它发送一个具有单个属性的JSON对象,该属性本身就是一个数组。由于JSON.NET无法将对象解析为数组,因此您会收到400状态代码。

为进一步说明,这是您要发送的内容:

@Stateless
public class UsuarioServicio {

    @PersistenceContext(unitName = "XinsPU")
    private EntityManager em;


    public List<Usuario> listado() throws Exception{
        Query consulta = em.createQuery("SELECT u FROM Usuario u");
        return consulta.getResultList();
    }

    //Never rollback transaction. With or without @Transactional anotation
    //@Transactional( rollbackOn={MiExcepcion.class } )
    public boolean eliminarUsuarios() throws Excepcion{                        
        List<Usuario> listaUsuarios = listado();                
        for(Usuario u : listaUsuarios){
            em.remove(u);
        }                
        em.flush();     

        throw new MiExcepcion();

        return true;
    }

但是,这是预期的数组,因此应如下所示:

@ApplicationException(rollback=true)
public class MiExcepcion extends RuntimeException {

您需要做的就是将当前的{ "assignees": [ { ... assignee1 ... }, { ... assignee2 ... }, ... ] } 行更改为此:

[
    { ... assignee1 ... },
    { ... assignee2 ... },
    ...
]

另一种选择是在ASP.NET Core项目中创建一个模型类,并使用它代替字符串列表。如下所示:

JSON.stringify

JSON.stringify(assignmentPage.SelectedUsers) 操作如下所示:

public class AssignmentModel
{
    public List<UserViewModel> Assignees { get; set; }
}

答案 1 :(得分:1)

我的情况是我正在使用AutoValidateAntiforgeryTokenAttribute配置

services.AddMvc(options =>{
    // Automatically add antiforgery token valdaiton to all post actions.
    options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
}

因此,ajax发布本身没有任何请求验证令牌,缺少此令牌服务器将返回错误的请求。

为克服这个问题,我遵循了link,因此我的最终工作代码为

Assignment.cshtml

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions
{
    public string GetAntiXsrfRequestToken() => Xsrf.GetAndStoreTokens(Context).RequestToken;
}
<input type="hidden" id="RequestVerificationToken" name="RequestVerificationToken" 
       value="@GetAntiXsrfRequestToken()">

<script type="text/javascript">
    $("#btn-saveinspectors").click(function () {
        var url = "/Audit/Assignment/@Model.SelectedUser.Id";
        var assignees = JSON.stringify(assignmentPage.SelectedUsers);

        $.ajax({
            type: "POST",
            url: url,
            beforeSend: function (xhr) {
                xhr.setRequestHeader("XSRF-TOKEN", $('#RequestVerificationToken').val());
            },
            contentType: "application/json",
            data: assignees,
        });
    });
</script>

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
}

注意:这是我的情况,我的页面中没有没有表单,该表单会自动生成请求验证令牌。如果您的页面中有一个表单,您在其中提出了ajax请求,那么您可以按照this post