Form in Razor Pages
This article describes how to seamlessly integrate and configure the Telerik UI Form for ASP.NET Core in Razor Pages applications.
Referencing Handler Methods in Razor Pages
Razor Pages is an alternative to the MVC pattern that makes page-focused coding easier and more productive. This approach consists of a cshtml file and a cshtml.cs file (by convention, the two files have the same name).
The cshtml.cs file, known as the PageModel, contains handler methods that respond to HTTP requests. These methods are prefixed with On followed by the HTTP verb (for example, OnGet, OnPost, OnPostRead, OnPostCreate).
Handler methods declared in a PageModel can be referenced from any Razor Page using one of the following URL patterns:
-
Using
Url.Page()C#Url.Page("PageName", "HandlerName") // OR Url.Page("/FolderName/PageName", "HandlerName")For example,
Url.Page("Index", "Read")references theOnPostReadorOnGetReadhandler method in theIndex.cshtml.csfile. -
Using a query string
C#Url("/PathToPage?handler=HandlerName")For example,
Url("/Index?handler=Read")references theOnPostReadorOnGetReadhandler method in theIndexpage.
For more information on Razor Pages architecture and concepts, refer to the official Microsoft documentation.
Standard Form Submit
By default, when the View containing the Form is loaded, clicking on the Submit button will fire the client-side validation of the Form component. Once all of the Form fields are filled and the user clicks on the Submit button the form will be submitted and the page will reload to display the server validation messages from the page model, if any.
When a complex model is used, as in the Razor Page scenario, the Form needs the FormData() configuration set.
Also, since the Form makes a POST request, the antiforgery token must be included in the request. This can be achieved, for example, by appending a hidden input to the Form.
See the implementation details in the example below, and for the full project with RazorPages examples, visit our GitHub repository.
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@{
var token = Xsrf.GetAndStoreTokens(HttpContext).RequestToken;
}
@(Html.Kendo().Form<OrderViewModel>()
.Name("formExample")
.FormData(Model.Order)
.Layout("grid")
.Grid(g => g.Cols(2).Gutter(20))
.HtmlAttributes(new { method = "POST" })
.Validatable(v =>
{
v.ValidateOnBlur(false);
v.ValidationSummary(true);
v.ErrorTemplate("<span style='color: red'>#:message#</span>");
})
.Items(items =>
{
items.Add()
.Field(f => f.ShipName)
.Label(l => l.Text("Ship Name:"));
items.Add()
.Field(f => f.ShipCity)
.Label(l => l.Text("Ship City"));
items.Add()
.Field(f => f.OrderDate)
.Editor(e => e.DatePicker())
.Label(l => l.Text("Order Date:"));
items.Add()
.Field(f => f.Freight)
.Editor(e => e.NumericTextBox())
.Label(l => l.Text("Freight:"));
})
)
<script>
$("#formExample").append($("<input type='hidden' name='__RequestVerificationToken' value='@token' data-stop='true' />"))
</script>Submitting the Form with Ajax
When the Form is submitted with ajax, the default submit event of the component is prevented, thus forcing the manual implementation of the submit behavior. In this case, an ajax request is sent to a specific end-point on Submit click, without reloading the page and client-side validation will work as expected. However, for server validation, as the page is not reloaded and the page model data is not changed, the Telerik Validator attached to the Form has no way of knowing what the server response is. For this reason, the ajax request callback can be used to notify the user of the status of the server validation. If the server end-point is returning validation errors related to the Form fields the error callback can be used to iterate over the response errors and create a visual representation in the UI. In a similar way the success callback can be used to notify the user of a succesful Form submission.
When a complex model is used, as in the Razor Page scenario, the Form needs the FormData() configuration set.
See the implementation details in the example below, where the JSON errors are appended to the validation summary and it is toggled it in the ajax success and error callbacks. For the full project with RazorPages examples, visit our GitHub repository.
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@{
var token = Xsrf.GetAndStoreTokens(HttpContext).RequestToken;
}
<div id="validation-success"></div>
@(Html.Kendo().Form<OrderViewModel>()
.Name("formExample")
.FormData(Model.Order)
.Layout("grid")
.Grid(g => g.Cols(2).Gutter(20))
.HtmlAttributes(new { method = "POST" })
.Validatable(v =>
{
v.ValidateOnBlur(false);
v.ValidationSummary(true);
v.ErrorTemplate("<span style='color: red'>#:message#</span>");
})
.Items(items =>
{
items.Add()
.Field(f => f.ShipName)
.Label(l => l.Text("Ship Name:"))
.Hint("Hint: Entering Ship Name other than \"John Doe\" will cause the server validation to fail");
items.Add()
.Field(f => f.ShipCity)
.Label(l => l.Text("Ship City"));
items.Add()
.Field(f => f.OrderDate)
.Editor(e => e.DatePicker())
.Label(l => l.Text("Order Date:"));
items.Add()
.Field(f => f.Freight)
.Editor(e => e.NumericTextBox())
.Label(l => l.Text("Freight:"));
})
.Events(ev => ev.Submit("onFormSubmit").Clear("onFormClear"))
)
<script>
function onFormClear(e) {
$("#validation-success").html("");
};
function onFormSubmit(ev) {
ev.preventDefault();
var modelData = ev.model;
modelData.OrderDate = modelData.OrderDate.toJSON();
$.ajax({
type: 'POST',
url: "@Url.Page("FormAjaxSubmit","Submit")",
beforeSend: function (xhr) {
xhr.setRequestHeader("RequestVerificationToken",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
data: modelData,
dataType: 'json',
success: function (data) {
var form = $("#formExample").getKendoForm();
form.validator.validationSummary.find("ul").empty();
form.validator.validationSummary.addClass("k-hidden");
$("#validation-success").html("<div class='k-messagebox k-messagebox-success'>" + data.success + "</div>");
},
error: function (data) {
var response = JSON.parse(data.responseText);
var form = $("#formExample").getKendoForm();
var errorString = "";
$.each(response.errors, function (key, value) {
errorString += '<li>' + value + '</li>';
});
$("#validation-success").html("");
form.validator.validationSummary.find("ul").empty();
form.validator.validationSummary.find("ul").append(errorString);
form.validator.validationSummary.toggleClass("k-hidden");
}
})
};
$("#formExample").append($("<input type='hidden' name='__RequestVerificationToken' value='@token' data-stop='true' />"))
</script>