c# - How can I change the input element name attribute value in a razor view model using a custom attribute in a model? -
i have following:
@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>
as can see creating input element.
the view model passed view contains following:
public class searchboxviewmodel { [required] [display(name = "search")] public string searchphrase { get; set; } }
at moment input element contains name attribute value of "searchphrase" value "q" without renaming property.
i prefer extension allows me call textboxfor without need of having supply name property, custom attribute somehow sets value of name property automatically value specified in custom attribute.
the following example of mean:
public class searchboxviewmodel { [required] [display(name = "search")] [input(name = "q")] public string searchphrase { get; set; } }
combined with:
@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>
which produce similar following:
<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>
i custom attribute take effect whenever searchboxviewmodel used regardless of template used prevent errors, intention of being clear programmers, while creating user-friendly query string user.
is possible using custom attribute on searchphrase property in similar fashion how display name changed?
i wrote simple can start write complete solution.
first wrote simple attribute
name provided:
public class inputattribute : attribute { public string name { get; set; } }
then wrote html helper wraps default textboxfor
, searches input
attribute , if any, replace name attribute of generated htmlstring
textboxfor
:
public static mvchtmlstring mytextboxfor<tmodel, tproperty>(this htmlhelper<tmodel> htmlhelper, system.linq.expressions.expression<func<tmodel, tproperty>> expression, object htmlattributes) { var memberexpression = expression.body memberexpression; var attr = memberexpression.member.getcustomattribute(typeof (inputattribute)) 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; }
then use html helper in razor views:
@html.mytextboxfor(m => m.searchphrase, new { @class = "form-control" })
also model follows:
public class searchboxviewmodel { [required] [display(name = "search")] [input(name = "q")] public string searchphrase { get; set; } }
this way complete solution:
- you have implement of overloads of
textboxfor
- if try send form data action parameter of type
searchboxviewmodel
404 becausemodelbinder
can not bind request parametersviewmodel
. have writemodelbinder
solve problem. - you have write
labelfor
accordingly matchfor
attribute correctly.
edit: in case of problem don't have deal case 2 because send get
request , form parameters in query string. may write action signature like:
public actionresult search(string q) { // use q search }
the problem occurs when have non-primitive type in action parameters. in case modelbinder
tries match query string items (or request payload) properties of type of action parameter. example:
public actionresult search(searchboxviewmodel vm) { // ... }
in case, query string (or request payload) has search query in parameter named q
(because name of input q
, html form sends request in form of key-values consist of input name , input value). mvc can not bind q
searchphrase
in loginviewmodel
, 404.
Comments
Post a Comment