This is a migrated thread and some comments may be shown as answers.

ASP.NET MVC With WebApi and Attribute Routing

5 Answers 339 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Joel
Top achievements
Rank 1
Joel asked on 28 Feb 2018, 08:57 PM

I'm attempting to test out how the Telerik (Kendo) grid will work in a current application I have but am running into some roadblocks.

I have a WebApi controller which inherits from ApiController and implements the following "Get" method:

[System.Web.Http.HttpGet, System.Web.Http.Route(LookupUrl.MyLookup)] public DataSourceResult Get([System.Web.Http.ModelBinding.ModelBinder(typeof(WebApiDataSourceRequestModelBinder))]DataSourceRequest request)        

{

            return service.GetModels().ToDataSourceResult(request);

}

and in the .cshtml file I have:

@(Html.Kendo().Grid<MyModel>()           .Name("telerikGrid")           .Columns(col =>           {               col.Bound(c => c.Key);               col.Bound(c => c.DisplayName);               col.Bound(c => c.Inactive);           })           .Scrollable()           .Groupable()           .Sortable()           .Filterable()           .Pageable(pageable => pageable               .Refresh(true)               .PageSizes(true)               .ButtonCount(5))           .DataSource(d =>               d.WebApi()                   .Model(model =>                   {                       model.Id(p => p.Key);                   })                   .Events(events => events.Error("error_handler"))                   .Read(read => read.Url(Url.ApiUrl(LookupUrl.MyLookup)))           )     )

 

The grid shows up correctly on the page, but the controller method is never accessed.  I'm not entirely sure what I am doing wrong here.

5 Answers, 1 is accepted

Sort by
0
Joel
Top achievements
Rank 1
answered on 28 Feb 2018, 09:30 PM
Update to this. I have figured out my problem with the "Get" method not getting called and it is now getting hit properly. My problem now is that even though the "data" property of the return value has the correct number of records and the correct data in it, the results are not displayed on the screen.
0
Joel
Top achievements
Rank 1
answered on 01 Mar 2018, 12:49 AM

Update...again.  I added code to my .cshtml file to see where the response was going (other than into the abyss):

@(Html.Kendo().Grid<Helion.Orcats.Models.Workflow.WorkflowUser>()       .HtmlAttributes(new Dictionary<string, object> { { "style", "width: 700px;" } })       

.Name("WorkflowUsers")       

.Columns(col =>       {           

     col.Bound(c => c.UserKey);           

     col.Bound(c => c.DisplayName);           

     col.Bound(c => c.Inactive);       })       

.Scrollable()       

.Groupable()       

.Sortable()       

.Filterable()       

.Pageable(pageable => pageable           

     .Refresh(true)           

     .PageSizes(true)           

     .ButtonCount(5))       

.DataSource(d =>           

     d.WebApi()               

       .Model(m => { m.Id(p => p.UserKey); })               

       .Read(read => read.Url(Url.ApiUrl(LookupUrl.WorkflowUsers_T)))               

       .Events(events =>               {                   

               events.Error("error_handler");                   

               events.Sync("sync_handler");                   

               events.RequestEnd("request_end");               

})  ))

 

When the request ends, I use a console.log to see what is in the argument and he data is there.  How do I make sure that data gets set as the data source for the grid?

 

0
Boyan Dimitrov
Telerik team
answered on 02 Mar 2018, 11:53 AM
Hello,

One of the main functionalities of the ToDataSourceResult extension method is to create a Data property in the response object. The DataSource expects this property to be named "Data" with capital D. If for some reason the data property (where items are stored in the response) is named with small letters the DataSource will not find the items. 

Such situation can occur in ASP.NET Core. By default the json output is camelCase, but the "Data" is PascalCase. In our Getting Started article and specifically step 4 

// Maintain property names during serialization. See:
services
    .AddMvc()
    .AddJsonOptions(options =>
        options.SerializerSettings.ContractResolver = new DefaultContractResolver());
 
// Add Kendo UI services to the services container

the JSON serializer settings are changed to avoid this problem. 

Regards,
Boyan Dimitrov
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Joel
Top achievements
Rank 1
answered on 02 Mar 2018, 03:57 PM
[quote]Boyan Dimitrov said,

One of the main functionalities of the ToDataSourceResult extension method is to create a Data property in the response object. The DataSource expects this property to be named "Data" with capital D. If for some reason the data property (where items are stored in the response) is named with small letters the DataSource will not find the items. 

Such situation can occur in ASP.NET Core. By default the output is camelCase, but the "Data" is PascalCase. In our Getting Started article and specifically step 4 

// Maintain property names during serialization. See:
services
    .AddMvc()
    .AddJsonOptions(options =>
        options.SerializerSettings.ContractResolver = new DefaultContractResolver());
// Add Kendo UI services to the services container

the JSON serializer settings are changed to avoid this problem. 

Regards,
Boyan Dimitrov
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.

[/quote]

While you are correct (I figured it out last night) that the problem was  in the JSON data in the response, globally changing the case to Pascal Case would break the rest of the application.  I ended up intercepting the response and changing the contract resolver locally. I am trying to find a more ".NET" way of doing it, but until then the following code fixed it:

[System.Web.Http.HttpGet, System.Web.Http.Route(LookupUrl.MyModels)]
        public HttpResponseMessage Get([System.Web.Http.ModelBinding.ModelBinder(typeof(WebApiDataSourceRequestModelBinder))]DataSourceRequest request)
        {
            return Request.CreateResponse(HttpStatusCode.OK, service.MyModels().ToDataSourceResult(request), GetFormatter());
        }
 
        private JsonMediaTypeFormatter GetFormatter()
        {
            var f = new JsonMediaTypeFormatter
            {
                SerializerSettings = new JsonSerializerSettings {ContractResolver = new DefaultContractResolver()}
            };
 
            return f;
        }
0
Joel
Top achievements
Rank 1
answered on 02 Mar 2018, 04:01 PM
Oh and in case anyone is interested, this is not something I am doing in ASP.NET Core. This is an ASP.NET MVC app with WebApi.  To change the contract resolver globally (at least for WebApi), you need to go into the WebApiConfig.cs file and change it. If you want to change that file it looks like this:

public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
 
           config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver();
        }
Tags
Grid
Asked by
Joel
Top achievements
Rank 1
Answers by
Joel
Top achievements
Rank 1
Boyan Dimitrov
Telerik team
Share this question
or