如何绑定 Kendo.MVC DataSource Read in WebApi using Ajax Request on Razor page

How to bind Kendo.MVC DataSource Read in WebApi using Ajax Request on Razor page

我有一个定义如下的网格

@(Html.Kendo().Grid<DtoStuff>()
        .Name("grid")
        .Columns(columns =>
        {
            columns.Bound(c => c.Number);
            columns.Bound(c => c.Date);
            columns.Bound(c => c.Total);    
        })
        .Reorderable(reorderable => reorderable.Columns(true))
        .Resizable(resizable => resizable.Columns(true))
        .Pageable()
        .Filterable(f => f.Extra(false).Mode(GridFilterMode.Menu))
        .Sortable(sorting => sorting.SortMode(GridSortMode.SingleColumn).AllowUnsort(false))
        .ColumnMenu()
        .DataSource(dataSource => dataSource
            .Ajax()
            .ServerOperation(true)
            .PageSize(15)
            .Model(model => model.Id(p => p.Number))
            .Read(read => read
                .Url("https://local-api.net/Customer/v1/Stuff/Stuffs")
                )
            .Sort(s => s.Add("Date").Descending())
            .Filter(f => f.Add(a => a.Date).IsGreaterThanOrEqualTo(DateTime.Now.AddYears(-1)))
    )
)

我想添加一个自定义授权令牌,主要是:http://www.telerik.com/forums/cannot-add-a-custom-http-header

但是当我这样做时,发送的参数都搞砸了,我不知道如何正确解析它们。

这是将 Header 添加到数据源

的脚本
<script>
    $(function () {
        var grid = $("#grid").data("kendoGrid");

        grid.dataSource.transport.options.read.beforeSend = function (xhr) {
            xhr.setRequestHeader('Authorization', 'Bearer @Session["Authorization"]');
        };
        grid.dataSource.read();
    });
</script>

这里是 WebApi 中的控制器 Controller.cs

 [HttpPost, Route("Stuffs")]
public IHttpActionResult PostStuffs([DataSourceRequest] DataSourceRequest request)
    {
        if (ModelState.IsValid)
        {
            using (var entities = dboModel.Value)
            {
                var query = entities.Stuff
                    .ProjectToType<DtoStuff>();

                request = request == null ? new DataSourceRequest() : request;

                var result = query.ToDataSourceResult(request);

                return Ok(result);
            }
        }
        else
        {
            return BadRequest("Request is not Valid");
        }
    }

概览

客户端 (CSHTML)

  1. 确保数据源读取操作不会自动绑定
  2. 将数据源设置为 Ajax
  3. 将 ServerOperation 设置为 true
  4. 使用 Type = GET 设置读取操作(重要)

应该看起来像:

@(Html.Kendo().Grid<DtoStuff>()
            .Name("grid")
            .Columns(columns =>
            {
                columns.Bound(c => c.Number);
                columns.Bound(c => c.Date)
                columns.Bound(c => c.Total);

            })
            .Reorderable(reorderable => reorderable.Columns(true))
            .Resizable(resizable => resizable.Columns(true))
            .Pageable()
            .Filterable(f => f.Extra(false).Mode(GridFilterMode.Menu))
            .ColumnMenu()
            .AutoBind(false)
            .DataSource(dataSource => dataSource
                .Ajax()
                .ServerOperation(true)
                .PageSize(15)
                .Model(model => model.Id(p => p.Number))
                .Read(read => read
                    .Url("https://local-api.net/Customer/v1/Stuff/Stuffs")
                    .Type(HttpVerbs.Get)
                    )
                .Sort(s => s.Add("Date").Descending())
                .Filter(f => f.Add(a => a.Date).IsGreaterThanOrEqualTo(DateTime.Now.AddYears(-1)))
        )
    )

客户端(脚本)

  1. 添加 beforeSend 匿名函数,如下所示:http://www.telerik.com/forums/cannot-add-a-custom-http-header

     $(function () {
        var grid = $("#grid").data("kendoGrid");
    
        grid.dataSource.transport.options.read.beforeSend = function (xhr) {
            xhr.setRequestHeader('Authorization', 'Bearer @Session["Authorization"]');
            if('@Session["StuffedHeader"]' != '')
            {
                xhr.setRequestHeader('StuffedHeader', '@Session["StuffedHeader"]');
            }
        };
        grid.dataSource.read();
    });
    

服务器端(Controller.cs)

  1. 创建选项请求(CORS 需要)
  2. 使用这个作为请求参数实现get请求:

[ModelBinder(typeof(WebApiDataSourceRequestModelBinder))] DataSourceRequest request

  1. 选择添加的位置'Access-Control-Allow-Origin'
  2. 使用 [EnableCors("", "","*")]
  3. 使用response.Headers.Add("Access-Control-Allow-Origin","*");在 OptionMethod

    [RoutePrefix("FluffyThings/v1/Stuff")]
    
    [EnableCors("*", "*","*")]
    
    public class StuffController : ApiController
    {
    
        [HttpGet, Route("Stuffs")]
    
        public IHttpActionResult Get([ModelBinder(typeof(WebApiDataSourceRequestModelBinder))] DataSourceRequest request)
        {
            return PostStuffs(request);
        }
    
        [HttpPost, Route("Stuffs")]
    
        public IHttpActionResult PostStuffs([DataSourceRequest] DataSourceRequest request)
        {
            if (ModelState.IsValid)
            {
                using (var entities = dboModel.Value)
                {
                    var query = entities.stuff.ProjectToType<DtoStuff>();
    
                    request = request == null ? new DataSourceRequest() : request;
    
                    var result = query.ToDataSourceResult(request);
    
                    return Ok(result);
                }
            }
            else
            {
                return BadRequest("Request is not Valid");
            }
        }
    
        [HttpOptions, Route("Stuffs")]
        public HttpResponseMessage OptionsStuffs()
        {
            HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
            //Use this to allow specific origin to access content
            //response.Headers.Add("Access-Control-Allow-Origin", "*");
            response.Headers.Add("Access-Control-Allow-Methods", "POST, GET");
            response.Headers.Add("Access-Control-Max-Age", "3600");
            response.Headers.Add("Access-Control-Allow-Headers", "Authorization, StuffHeader");
    
            return response;
        }
    }