所以我对使用 Razor Pages 进行实验的 Asp.Net 框架还比较陌生。我面临模型绑定的问题。似乎没有按预期工作。
这是我的剃须刀页面。在“OnGet”操作中,我正在动态构建一个表单。仅对于某些上下文,该表单将具有大约三种输入:文本输入、日期输入、选择和多选输入。
QueryField
类基本上代表每种输入类型。 Name
属性代表参数名称,Required
代表该字段是否必填等等...
namespace ReportViewer.Pages
{
public class QueryField
{
public string Name { get; set; }
public string Label { get; set; }
public string Type { get; set; }
public bool Required { get; set; }
public List<string> Values { get; set; }
}
public class ReportModel : PageModel
{
private readonly AlertService _alertService;
private readonly ApplicationDbContext _dbContext;
public Report Report {get; set;}
[BindProperty]
public List<QueryField> Fields { get; set; }
public ReportModel(AlertService alertService, ApplicationDbContext dbContext){
_alertService = alertService;
_dbContext = dbContext;
Fields = new List<QueryField>();
}
public void OnGet(string reportName)
{
var report = _dbContext.Report.FirstOrDefault(r=> r.Name == reportName);
if (report == null){
_alertService.AddAlert($"{reportName} is not a valid report. Please check your report name and try again", AlertType.Danger);
} else {
Report = report!;
var parameters = _dbContext.Parameter.Where( p=> p.ReportId == report.Id).ToList();
foreach (var parameter in parameters){
string FieldType;
if (parameter.ValidValues.Count() == 0){
if (parameter.ParameterType == "Integer"){
FieldType = "NumberInput";
} else if (parameter.ParameterType == "DateTime"){
FieldType = "DateInput";
} else {
FieldType = "TextInput";
}
} else {
if (parameter.MultiValue){
FieldType = "MultiSelectInput";
} else {
FieldType = "SelectInput";
}
}
QueryField field = new QueryField(){
Name = parameter.Name,
Label = parameter.Name,
Type = FieldType,
Required = parameter.Nullable,
Values = parameter.ValidValues,
};
Fields.Add(field);
}
}
}
public IActionResult OnPost(List<QueryField> formData)
{
if (!ModelState.IsValid){
return Page();
}
Console.WriteLine($"Fields: {formData.Count}");
return RedirectToPage("Report");
}
}
}
在html模板上..
@page "/Reports/{reportName}"
@model ReportViewer.Pages.ReportModel
@{
ViewData["Title"] = "ReportQuery";
}
@if (Model.Report != null){
<form data-parsley-validate role="form" id="DUBulkStatementReportForm" method="post">
<p>
Please enter/select required detail(s)<br>
<em><small>Fields marked<span style="color: red">*</span> are required</small></em>
</p>
<div class="row">
<div class="col-md-12">
<h3>@Model.Report.Name Parameters</h3>
<hr class="inner-separator" />
</div>
<div class="col-md-6">
<div class="col-md-12">
@if (Model.Fields != null)
{
// --- render form fields here..
@foreach (var field in Model.Fields)
{
<div class="form-group">
@if (field.Type == "NumberInput")
{
<input class="form-control" type="number" name="@field.Name" />
}
else if (field.Type == "DateInput")
{
@if (field.Required)
{
<p class="required">@field.Label</p>
}
else
{
<p>@field.Label</p>
}
<div class="input-group">
<span class="input-group-addon">
<i class="fa fa-calendar"></i>
</span>
<input type="text" class="form-control dateP" name="@field.Name">
</div>
}
else if (field.Type == "TextInput")
{
@if (field.Required)
{
<label for="@field.Name" class="form-control required">@field.Label</label>
<input type="text" class="form-control" id="@field.Name" required name="@field.Name" />
}
else
{
<label for="@field.Name" class="form-control">@field.Label</label>
<input type="text" class="form-control" id="@field.Name" name="@field.Name" />
}
}
else if (field.Type == "MultiSelectInput")
{
@if (field.Required)
{
<p class="required">@field.Label</p>
<select class="select2" multiple="multiple" multiple name="@field.Name" required>
@foreach (var value in field.Values)
{
<option value="@value">@value</option>
}
</select>
}
else
{
<p>@field.Label</p>
<select class="select2" multiple="multiple" multiple name="@field.Name">
@foreach (var value in field.Values)
{
<option value="@value">@value</option>
}
</select>
}
}
else if (field.Type == "SelectInput")
{
@if (field.Required)
{
<p class="required">@field.Label</p>
<select name="@field.Name" class="select2" required>
@foreach (var value in field.Values)
{
<option value="@value">@value</option>
}
</select>
}
else
{
<p>@field.Label</p>
<select name="@field.Name" class="select2">
@foreach (var value in field.Values)
{
<option value="@value">@value</option>
}
</select>
}
}
</div>
}
}
</div>
<div class="col-md-12">
<div class="form-group">
<button id="PrintPDF" type="button" class="btn btn-info" style="display:inline">
<i class="fa fa-file-pdf-o"></i><b>Download PDF</b>
</button>
<button type="button" id="PrintEXCEL" class="btn btn-success" style="display:inline">
<i class="fa fa-file-excel-o"></i><b>Download EXCEL</b>
</button>
</div>
<!--Download PDF Confirmation Modal-->
<div class="modal fade" id="DownloadPDFReportModal" data-backdrop="static" data-keyboard="false"
tabindex="-1" role="dialog" style="margin: 0 auto;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h4 class="modal-title"><i class="fa fa-check-square-o success"></i> Download
{{report.name}} Confirmation</h4>
</div>
<div class="modal-body">
<p><strong>Are you sure you want to continue downloading report?</strong></p>
<p>Click No if you would like to cancel. Click Yes to continue.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">No</button>
<button type="button" class="btn btn-success" data-dismiss="modal"
id="ConfirmDownloadPdf">Yes</button>
</div>
</div>
</div>
</div>
<!--End of PDF Confirmation Modal-->
<!--Download EXCEL Confirmation Modal-->
<div class="modal fade" id="DownloadEXCELReportModal" data-backdrop="static" data-keyboard="false"
tabindex="-1" role="dialog" style="margin: 0 auto;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h4 class="modal-title"><i class="fa fa-check-square-o success"></i> Download
{{report.name}} Confirmation</h4>
</div>
<div class="modal-body">
<p><strong>Are you sure you want to continue downloading report?</strong></p>
<p>Click No if you would like to cancel. Click Yes to continue.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">No</button>
<button type="button" class="btn btn-success" data-dismiss="modal"
id="ConfirmDownloadExcel">Yes</button>
</div>
</div>
</div>
</div>
<!--End of EXCEL Confirmation Modal-->
<!--Download Wait Modal-->
<div class="modal fade" id="ReportDownloadWaitModal" data-backdrop="static" data-keyboard="false"
tabindex="-1" role="dialog" style="margin: 0 auto;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h4 class="modal-title text-success"><i class="fa fa-check-square-o success"></i>
Downloading File...</h4>
</div>
<div class="modal-body text-success" id="successMessage">
<p>Please wait while the file is being downloaded...</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Ok</button>
</div>
</div>
</div>
</div>
<!--End of Download Wait Modal-->
</div>
</div>
</div>
</form>
}
表格呈现良好。我遇到的问题是在
OnPost
操作处理程序上。我希望如果绑定按预期工作,字段将被填充,但情况似乎并非如此。在这种情况下,打印 formData.Count
给我 0 表明
也许绑定不起作用。但是,如果我调用 Request.Form["field_name"]
,我可以在请求中看到表单数据。我更愿意采用绑定方法,而不是解析来自 Request 对象的数据。
我不确定我错过了什么,或者我是否以正确的方式做事。如有任何帮助,我们将不胜感激。
您需要绑定 name 属性,如:
name="formData[@i].Name"
,将 name 值绑定到 OnPost(List formData
) (QueryField Name)。
您可以尝试删除
@foreach (var field in Model.Fields)
并添加 @for (var i = 0; i< Model.Fields.Count; i++ )
,例如:
@if (Model.Fields != null)
{
@for (var i = 0; i< Model.Fields.Count; i++ )
{
// --- render form fields here..
<div class="form-group">
@if (Model.Fields[@i].Type == "NumberInput")
{
<input class="form-control" type="text" name="formData[@i].Name" />
}
else if (Model.Fields[@i].Type == "DateInput")
{
@if (Model.Fields[@i].Required)
{
<p class="required">@Model.Fields[@i].Label</p>
}
else
{
<p>@Model.Fields[@i].Label</p>
}
<div class="input-group">
<span class="input-group-addon">
<i class="fa fa-calendar"></i>
</span>
<input type="text" class="form-control dateP" name="formData[@i].Name">
</div>
}
...
记住将
field
更改为Model.Fields[@i]
。然后我们可以得到List<QueryField> formData
,如下所示:
注意 我们会遇到 ModelState.IsValid 为 false,因为 QueryField 中的其他属性没有传递给 Post 方法。