This was my first time using Telerik and although there are some good things you can do with it, it’s hard to find help whenever you attempt something that is just outside what is shown in their demos and there is so many different ways to hook it up. This post docos what I’ve done when implementing a master-detail grid using KendoUI for an IIS site with windows authentication.
As this is for an intranet I’ve used windows authentication with 2 roles, one for read and another for writes.
Visual Studio Community 2017
.NET Core 2.0 Runtime
Open VS2017 and create a new project and choose your target (.NET Core or .NET Framework). I’ve chosen the full framework because later I want to use Telerik Reporting (which as yet hasn’t been converted to standard)
Update all packages to the latest.
Packages for DB
If you targeted standard instead of full in the previous step you could just get away with including the “Microsoft.AspNetCore.All” package. If targeting full include the following nuget packages (in order).
To setup Telerik Nuget Package Source in VS2017. (ref. https://docs.telerik.com/aspnet-mvc/getting-started/nuget-install#set-up-nuget-package-source)
In the package manager console run:
NuGet Sources Add -Name "telerik.com" -Source "https://nuget.telerik.com/nuget" ^
-UserName "your login email" -Password "your password" ^
Open NuGet.Config from %AppData%\Nuget and it should look similar to this.
Visual Studio should now have another entry in NuGet.
Add the Telerik.UI.for.AspNet.Core package.
The database is simple with only a few tables. The master/parent table (Tag) and the detail/child (Alarm). Alarms have a few look ups and a boolean and date field, to show different data types.
DB Create Script
The script below creates 10000 Tags with 2-5 Alarms each and the lookup tables.
Generate Model Classes
In the Package Manager Console run the following.
The project should now have these classes.
Delete the OnConfiguring method in the DbContext class.
Add a constructor, which is used for dependency injection.
In appsettings.json add the connection string.
Register the DB Context
In Startup.cs register the db context. (note: add the using statement for Microsoft.EntityFrameworkCore)
NOTE: use the new db context pool only if your context class does not store any state within it.
As this example doesn’t store any state the AddDbContextPool method is used, otherwise fall back to services.AddDbContext().
Authorization policies are more flexible than just decorating a controller/method with [Authorize(“ADGroup”)] and allow easy changes within appsettings.json. The following will create 2 model classes (AuthPolicy and AuthMember) and a settings class which will get its values from appsettings.json. It will also show how to initialize the settings in Startup.cs and how to inject it into controllers and views. The Settings class has 2 policies, one for READ and one for WRITE.
Create a new folder at the project root called Auth, and add a new class file Auth.cs, with the following code.
Note: add the using statement for Microsoft.Extensions.DependencyInjection.
Add the following to appsettings.json.
Replace the values with your AD Groups/users. The above settings give read access to all Domain Users, while write access is restricted to user1 OR members of the WriteAccessGroup.
To restrict the policy to allow members which belong to 2 groups, use the members array. i.e.
Meaning WriteAccess is given to users who belong to OfficeStaff AND EngineeringStaff.
Initialize the AuthPolicySettings
In ConfigureServices method of Startup.cs add the following code at the start of the method.
Line 1 reads the settings out of appsettings.json. Line 2 and 3 instantiates the classes and line 4 sets it up for dependency injection.
This Auth can be used 3 ways.
Decorate controller classes with attribute. This example lets ReadAccess users to view Index but not the About page. Note: this is only an example, you wouldn’t really expect the About page to be restricted to the write group.
Dependency Injection into Controller
Include IAuthorizationService parameter into a controller.
Inject into View
Add the using and inject statements at the top of the razor page.
Call the AuthorizeAsync method on the service. Similar to above in the controller.
This next step changes the code generator template for “API Controller with actions, using Entity Framework” so that it matches the Kendo signature. This technique will allow complete control over the code generation just for the project.
Create a new folder structure at the solution root.
Copy “ApiControllerWithContext.cshtml” from “C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.visualstudio.web.codegenerators.mvc\2.0.0\Templates\ControllerGenerator” into the newly created folder. Note: the file can also be found at C:\Users\*YOU*\.nuget\packages\microsoft.visualstudio.web.codegenerators.mvc\1.1.1\Templates\ControllerGenerator
Replace the contents with the following. (hint: do it outside of VS so that it bypasses formatting)
Test it out by creating a WebApi for the AlarmReviewStatus model.
Create a folder WebApi under Controllers. Right click it and choose Controller… (Note: if this is the first time then follow the prompts and add MVC dependencies). When the Add Scaffold screen appears select “API Controller with actions, using Entity Framework”.
Select AlarmReviewStatus for the model and your db context. Leave the default for the controller name.
The following file should be created.
Test it out by running the project and browsing to /api/AlarmReviewStatus. Should be pretty similar to the following.
Continue to do the same for the other models.
The WebApi folder should now look like this.
Setup Kendo and Json for use in the views
In Startup.cs register Kendo and set the Json options.
In Views\_ViewImports.cshtml add using statement.
Kendo UI Client-side Resources
Create a folder “kendo-ui” under wwwroot\lib, and copy js and styles from Telerik source. (mine at the time of writing was C:\Program Files (x86)\Progress\Telerik UI for ASP.NET Core R3 2017)
In Views\Shared\_Layout.cshtml remove the scripts at the bottom and replace them at the top. (I found this easier than remembering to use deferred() for the kendo controls)
You could use the <environment> tag to use the full files for Development and the minified ones for Production. I didn’t do that here because it’s only really useful when troubleshooting.
The 3 kendo styles (highlighted) can be replaced with 1 if you use the theme builder from Telerik (http://themebuilder.telerik.com/aspnet-core).
Copy all the razor templates from the Telerik source to Views\Shared\EditorTemplates. (mine at the time of writing was C:\Program Files (x86)\Progress\Telerik UI for ASP.NET Core R3 2017\wrappers\aspnetcore\EditorTemplates\razor).
In Startup.Configure() set it to use Request Localization.
Create a new view “Tags” in the Views\Home folder and change the HomeController to suit.
Build and run it to check that all is well.
The Tags (Parent) Grid
Now add the Tags grid. In the view, start with the bare minimum to get the Kendo grid doing something. In Tags.cshtml add the following.
Line 1 creates a kendo grid for the Tag model.
Line 2 gives it a name so that it can be referenced with jQuery.
Lines 3-15 set the data source.
Line 10 sets up the read action to the List method of the TagsController.
Line 13 hooks the error event. Doesn’t do too much but logs the error to console, which is really helpful when trouble shooting.
Line 16 shows all the columns by default. Expect to change this soon as you’ll want to specifically state your columns and widths. But for now it’s a nice quick start to get something on the screen.
Lines 17-19 sets up paging.
Run the project. The result should be similar to this.
Add some of the other functionality like sorting and filtering.
Add Refresh and bigger page sizes.
The view with extra functionality.
Add the edit/create/delete functionality. First in DataSource add the Update action, then add the command column (before or after the data columns, depending on what you feel like).
The grid should now look like this, with updates and saves.
The default option for edit mode is InLine, but there are other options. InLine or PopUp works well with the command buttons on each row. InCell is good for a batch save, but you have to do other stuff to handle that. This example doesn’t go into that. To change the mode to PopUp, add the Editable method on the grid.
Out of the box it looks like this.
This can be made prettier by adding an EditorTemplate for Tag. For now set the edit mode back to InLine and continue.
Updates should work successfully if you added yourself to the WriteAccess group. Change the config so that you are not in the WriteAccess group and try to update again. Have a look at the console log and drill down into the responseText of the xhr object. You’ll see the error.
Seeing the user can’t save, the edit button (or column) can be hidden. Change the command column to the following code (ref above in Auth Usage for the view).
Include yourself back into the WriteAccess group and add the create functionality. First add the create action to the DataSource, then add the create button on the tool bar of the grid.
Adding a new record.
Add the delete functionality in the same way. First add it to the DataSource, then add it next to the edit command.
If you try to delete right now it will fail because of the foreign key constraint. At least you get a hint of that from the Error event of the DataSource.
You could turn on cascade deletes or do an extra check on the TagsController to return a BadRequest if the Tag has children. Leave it for now until after the details grid.
The Alarms (Detail) Grid
Make use of the Kendo templates. Start a script tag and include a kendo grid for the Alarm model. Name it “TagGrid_#=Id#”. In order for the template grid to work properly the last method called on the detail grid must be ToClientTemplate(). Include the template in the parent grid with ClientDetailTemplateId().
If you run the above code, you’ll see the beginnings of the master-detail layout. Notice the id of the detail grid matches the Tag Id.
Continue adding the DataSource and columns to the Alarms grid. (Remember to keep the ToClientTemplate() as the last call).
To make it a bit easier to return Alarms filtered by a Tag, I’ve added an extra parameter “ParentTagId” to the List and Create methods on the AlarmsController.
The full details grid as follows.
The modifications to the AlarmsController
About time to explicitly code the columns. Remove the c.AutoGenerate(true); line and replace with the following. Start with the text fields first.
The description column takes up a lot of room on the grid, so we’ll drop that on this screen and change the edit mode to PopUp and show it there.
Remove the AlarmDescription column and add the lookups, AlarmType and ReviewStatus.
Firstly inject the db context to the Home Controller and use the ViewBag to hold the SelectList for AlarmType.
Add the column to the view.
The results for the view and InLine edit mode.
If you add a UIHint and Display attributes to the model class, it will flow through to the PopUp edit as well.
Do the same for ReviewStatusId (except bind it to a ComboBox instead of a DropDown).
Setup the data in the HomeController.
Create a new EditorTemplate named ComboBox. The content will be very similar to the Telerik GridForeignKey.cshtml file.
Decorate the ReviewStatusId property of the Alarm model.
Add the column to the child grid.
The results should be something similar to this, where Review Status can have a null value.
Tidy up those labels using the Display attribute on the Alarm model. At the same time hide the Id fields by setting the ScaffoldColumn attribute to false and show the ReviewedDate as a Date instead of DateTime.
If the checkbox has the extra label, you could get rid of it, seeing as the label is already there on the edit form. Change the Boolean editor template to have a blank label.
Last thing to fix is the long description should be bound to a bigger input box. As KendoUI don’t have a suitable control, create an editor template named TextArea.cshtml with the following content.
This will style a TextArea element to match the rest of the Kendo controls.
Set the UIHint for the AlarmDescription in the Alarm model.
And the results should be similar to this.
Add a Data method to the Create and Update actions of the Alarm Datasource.
Custom editor templates to replace the out-of-the-box edit popups and stretching the edit screen to full width.
Showing/hiding columns based on screen width.
Validation should be expanded to handle multiple column validation and multiple objects. And displaying those validation fails to the end user.
Telerik Reports project with some reports for Tags and Alarms and linked from the grids.
This has shown how to display parent/child relationships in a table like fashion with edits and simple validation using web api with authentication over the top of a SQL database.
I hope this example serves as a nice entry point to Kendo controls, web api and .NET Core.