加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 如何使用模型中的自定义属性更改剃刀视图模型中的输入元素

发布时间:2020-12-15 18:03:57 所属栏目:百科 来源:网络整理
导读:我有以下几点: @model Pharma.ViewModels.SearchBoxViewModeldiv class="smart-search" @using (Html.BeginForm("Index","Search",FormMethod.Get,new { @class = "form-horizontal",role = "form" })) { div class="form-group" div class="hidden-xs- col
我有以下几点:
@model Pharma.ViewModels.SearchBoxViewModel
<div class="smart-search">
    @using (Html.BeginForm("Index","Search",FormMethod.Get,new { @class = "form-horizontal",role = "form" }))
    {
        <div class="form-group">
            <div class="hidden-xs- col-sm-1 col-md-1 col-lg-1 text-right">
                @Html.LabelFor(m => m.SearchPhrase,new { @class = "control-label" })
            </div>
            <div class="col-xs-8 col-sm-8 col-md-9 col-lg-10">
                @Html.TextBoxFor(m => m.SearchPhrase,new { @class = "form-control" })
            </div>
            <div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
                <input type="submit" value="Search" class="btn btn-default" />
            </div>
        </div>
    }
</div>

你可以看到这是创建一个输入元素.

传递给视图的视图模型包含以下内容:

public class SearchBoxViewModel
{
    [Required]
    [Display(Name = "Search")]
    public string SearchPhrase { get; set; }
}

当前input元素包含一个值为“SearchPhrase”的name属性,但我希望该值只是“q”,而不重命名该属性.

我更喜欢一个扩展名,它允许我调用TextBoxFor,但不需要提供Name属性,所以自定义属性以某种方式将Name属性的值自动设置为custom属性中指定的值.

以下是我的意思的一个例子:

public class SearchBoxViewModel
{
    [Required]
    [Display(Name = "Search")]
    [Input(Name = "q")]
    public string SearchPhrase { get; set; }
}

结合:

@model Pharma.ViewModels.SearchBoxViewModel
<div class="smart-search">
    @using (Html.BeginForm("Index",new { @class = "form-control" })
            </div>
            <div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
                <input type="submit" value="Search" class="btn btn-default" />
            </div>
        </div>
    }
</div>

然后将产生类似于以下内容的内容:

<div class="smart-search">
    <form action="/Search/Index" method="get" class="form-horizontal" role="form">
        <div class="form-group">
            <div class="hidden-xs- col-sm-1 col-md-1 col-lg-1 text-right">
                <label for="Search" class="control-label">Search</label>
            </div>
            <div class="col-xs-8 col-sm-8 col-md-9 col-lg-10">
                <input type="text" name="q" id="Search" value="" class="form-control" />
            </div>
            <div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
                <input type="submit" value="Search" class="btn btn-default" />
            </div>
        </div>
    </form>
</div>

我希望这个自定义属性每当使用SearchBoxViewModel时生效,无论使用什么模板来防止错误,意图是向程序员清楚,同时为用户创建一个用户友好的查询字符串.

是否可以使用SearchPhrase属性的自定义属性与显示名称的更改方式类似?

解决方法

我写了一些简单的东西,但可以开始写出完整的解决方案.

首先我用你提供的名字写了一个简单的属性:

public class InputAttribute : Attribute
{
    public string Name { get; set; }
}

然后我写了一个Html帮助器,它包装默认的TextBoxFor并搜索Input属性,如果有的话,它将从TextBoxFor中替换生成的HtmlString的name属性:

public static MvcHtmlString MyTextBoxFor<TModel,TProperty>(this HtmlHelper<TModel> htmlHelper,System.Linq.Expressions.Expression<Func<TModel,TProperty>> expression,object htmlAttributes)
{
    var memberExpression = expression.Body as MemberExpression;

    var attr = memberExpression.Member.GetCustomAttribute(typeof (InputAttribute)) as InputAttribute;
    var result = htmlHelper.TextBoxFor(expression,htmlAttributes);
    if (attr != null)
    {
        var resultStr = result.ToString();
        var match = Regex.Match(resultStr,"name="w+"");
        return new MvcHtmlString(resultStr.Replace(match.Value,"name="" + attr.Name + """));
    }

    return result;
}

然后在剃刀视图中使用这个html助手:

@Html.MyTextBoxFor(m => m.SearchPhrase,new { @class = "form-control" })

另外你的模型如下:

public class SearchBoxViewModel
{
    [Required]
    [Display(Name = "Search")]
    [Input(Name = "q")]
    public string SearchPhrase { get; set; }
}

这是一种完成解决方案的方法:

>你必须实现TextBoxFor的所有重载
>如果您尝试将表单数据发送到具有SearchBoxViewModel类型的参数的操作,您将会收到一个404,因为ModelBinder无法将请求参数绑定到此ViewModel.所以你必须编写一个ModelBinder来解决这个问题.
>您必须编写LabelFor才能正确匹配属性.

编辑:如果您遇到问题,您不需要处理第二种情况,因为您发送GET请求,您将在查询字符串中获取表单参数.所以你可以写下你的动作签名:

public ActionResult Search(string q)
{
  // use q to search
}

当您的动作参数中有非原始类型时,会出现此问题.在这种情况下,ModelBinder会尝试将查询字符串项(或请求有效负载)与动作参数类型的属性相匹配.例如:

public ActionResult Search(SearchBoxViewModel vm)
{
  // ...
}

在这种情况下,查询字符串(或请求有效负载)在名为q的参数中进行搜索查询(因为输入名称为q,而html表单以键值的形式发送请求,包括输入名称和输入值).所以MVC不能将q绑定到SearchViewModel中的SearchPhrase,你会得到一个404.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读