如何从 OnActionExecuting 中的模型获取 属性 值
How to get a property value from model in OnActionExecuting
我正在开展一个 Asp.Net core 5
项目,目标是 .Net 5
、
在很多情况下,我在视图中使用了 select
列表,并且从列表中选择的值将受到 model
properties
.
之一的影响
我熟悉 Action filters
但在我的水平上是初学者,所以我尝试创建一个自定义过滤器来检查 model
中是否有任何 property
的值相等default_option
我将添加一个错误 model state
,所有这些代码都应该发生在 OnActionExecuting
方法中。
我试过的:
public class CheckDefaultOptionFromSelect : ActionFilterAttribute
{
/// <inheritdoc />
public override void OnActionExecuting( ActionExecutingContext context )
{
var model = ( (Controller) context.Controller ).ViewData.Model;
if ( model is not null )
{
foreach ( var property in model.GetType().GetProperties() )
{
if ( (string) model.GetType().GetProperty( property.Name ).GetValue( model ).ToString() == "default_option" )
{
context.ModelState.AddModelError( "" , "Please select an option" );
base.OnActionExecuting( context );
break;
}
}
}
}
}
在那些动作视图中会有这样一块:
<div class="col-lg-4 col-sm-6">
<div class="form-group">
<div class="form-control-wrap">
<select asp-for="PropertyName" asp-items="@(new SelectList(myCollection,"Id","Title") )" class="form-select form-control form-control-lg form-control-outlined" data-ui="lg" data-search="on">
<option value="default_option">Default Option</option>
</select>
<label asp-for="PropertyName" class="form-label-outlined"></label>
<span asp-validation-for="PropertyName" class="text-danger"></span>
</div>
</div>
</div>
最重要的一点是:
<select asp-for="PropertyName" asp-items="@(new SelectList(myCollection,"Id","Title") )" class="form-select form-control form-control-lg form-control-outlined" data-ui="lg" data-search="on">
<option value="default_option">Default Option</option>
</select>
问题:
当我使用 break points
调试时,我看到 ( (Controller) context.Controller ).ViewData.Model
总是 null
.
问题:
请问如何迭代所有 model
属性并检查值是否不等于 default_option
?
您需要获取如下模型数据:
public class CheckDefaultOptionFromSelect : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
context.ActionArguments.TryGetValue("model", out object model);
if (model is not null)
{
foreach (var property in model.GetType().GetProperties())
{
if ((string)model.GetType().GetProperty(property.Name).GetValue(model).ToString() == "default_option")
{
context.ModelState.AddModelError("", "Please select an option");
base.OnActionExecuting(context);
break;
}
}
}
}
}
整个测试代码:
型号:
public class Test2
{
public int Id { get; set; }
public string Title { get; set; }
}
public class TestViewModel
{
public string PropertyName { get; set; }
}
查看:
注意:因为你添加的modelstate是空键,所以asp-validation-for="PropertyName"
不会显示错误。务必添加<div asp-validation-summary="ModelOnly" class="text-danger"></div>
以显示所有模型错误。
@model TestViewModel
@{
var myCollection = new List<Test2>()
{
new Test2(){ Id=1,Title="aaa"},
new Test2(){Id=2,Title="bbb"},
new Test2(){Id=3,Title="ccc"}
};
}
<form method="post" asp-action="Index">
<div class="col-lg-4 col-sm-6">
<div class="form-group">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-control-wrap">
<select asp-for="PropertyName" asp-items="@(new SelectList(myCollection,"Id","Title") )" class="form-select form-control form-control-lg form-control-outlined" data-ui="lg" data-search="on">
<option value="default_option">Default Option</option>
</select>
<label asp-for="PropertyName" class="form-label-outlined"></label>
<span asp-validation-for="PropertyName" class="text-danger"></span>
</div>
</div>
</div>
<input value="Create" type="submit" />
</form>
控制器:
public IActionResult Index()
{
return View();
}
[HttpPost]
[ServiceFilter(typeof(CheckDefaultOptionFromSelect))]
public IActionResult Index(TestViewModel model)
{
if (ModelState.IsValid)
{
return View();
}
else
{
return View(model);
}
}
在Startup.cs中注册ActionFilterAttribute
:
services.AddScoped<CheckDefaultOptionFromSelect>();
我正在开展一个 Asp.Net core 5
项目,目标是 .Net 5
、
在很多情况下,我在视图中使用了 select
列表,并且从列表中选择的值将受到 model
properties
.
我熟悉 Action filters
但在我的水平上是初学者,所以我尝试创建一个自定义过滤器来检查 model
中是否有任何 property
的值相等default_option
我将添加一个错误 model state
,所有这些代码都应该发生在 OnActionExecuting
方法中。
我试过的:
public class CheckDefaultOptionFromSelect : ActionFilterAttribute
{
/// <inheritdoc />
public override void OnActionExecuting( ActionExecutingContext context )
{
var model = ( (Controller) context.Controller ).ViewData.Model;
if ( model is not null )
{
foreach ( var property in model.GetType().GetProperties() )
{
if ( (string) model.GetType().GetProperty( property.Name ).GetValue( model ).ToString() == "default_option" )
{
context.ModelState.AddModelError( "" , "Please select an option" );
base.OnActionExecuting( context );
break;
}
}
}
}
}
在那些动作视图中会有这样一块:
<div class="col-lg-4 col-sm-6">
<div class="form-group">
<div class="form-control-wrap">
<select asp-for="PropertyName" asp-items="@(new SelectList(myCollection,"Id","Title") )" class="form-select form-control form-control-lg form-control-outlined" data-ui="lg" data-search="on">
<option value="default_option">Default Option</option>
</select>
<label asp-for="PropertyName" class="form-label-outlined"></label>
<span asp-validation-for="PropertyName" class="text-danger"></span>
</div>
</div>
</div>
最重要的一点是:
<select asp-for="PropertyName" asp-items="@(new SelectList(myCollection,"Id","Title") )" class="form-select form-control form-control-lg form-control-outlined" data-ui="lg" data-search="on">
<option value="default_option">Default Option</option>
</select>
问题:
当我使用 break points
调试时,我看到 ( (Controller) context.Controller ).ViewData.Model
总是 null
.
问题:
请问如何迭代所有 model
属性并检查值是否不等于 default_option
?
您需要获取如下模型数据:
public class CheckDefaultOptionFromSelect : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
context.ActionArguments.TryGetValue("model", out object model);
if (model is not null)
{
foreach (var property in model.GetType().GetProperties())
{
if ((string)model.GetType().GetProperty(property.Name).GetValue(model).ToString() == "default_option")
{
context.ModelState.AddModelError("", "Please select an option");
base.OnActionExecuting(context);
break;
}
}
}
}
}
整个测试代码:
型号:
public class Test2
{
public int Id { get; set; }
public string Title { get; set; }
}
public class TestViewModel
{
public string PropertyName { get; set; }
}
查看:
注意:因为你添加的modelstate是空键,所以asp-validation-for="PropertyName"
不会显示错误。务必添加<div asp-validation-summary="ModelOnly" class="text-danger"></div>
以显示所有模型错误。
@model TestViewModel
@{
var myCollection = new List<Test2>()
{
new Test2(){ Id=1,Title="aaa"},
new Test2(){Id=2,Title="bbb"},
new Test2(){Id=3,Title="ccc"}
};
}
<form method="post" asp-action="Index">
<div class="col-lg-4 col-sm-6">
<div class="form-group">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-control-wrap">
<select asp-for="PropertyName" asp-items="@(new SelectList(myCollection,"Id","Title") )" class="form-select form-control form-control-lg form-control-outlined" data-ui="lg" data-search="on">
<option value="default_option">Default Option</option>
</select>
<label asp-for="PropertyName" class="form-label-outlined"></label>
<span asp-validation-for="PropertyName" class="text-danger"></span>
</div>
</div>
</div>
<input value="Create" type="submit" />
</form>
控制器:
public IActionResult Index()
{
return View();
}
[HttpPost]
[ServiceFilter(typeof(CheckDefaultOptionFromSelect))]
public IActionResult Index(TestViewModel model)
{
if (ModelState.IsValid)
{
return View();
}
else
{
return View(model);
}
}
在Startup.cs中注册ActionFilterAttribute
:
services.AddScoped<CheckDefaultOptionFromSelect>();