41

I know that what I'm trying to do is bad idea, but I have specific constrains for now.

I have multiple sites, using one and the same MVC3 code base. For one of them the requirement is to hide some required fields from the form.

I know that the best approach is to modify the controller to set the defaults for these fields, but I'd like to achieve this modifying only the view for this particular site w/o changing the code.

So, how do I set a particular model property to a default value in the view? The ideal should be something like:

@Html.HiddenFor(model => model.RequiredProperty)
@model.RequiredProperty = "default"

EDIT: more explanation

So, actually this is in a sub-view, which is used by 2 different main views. I need these properties set only if one particular main view is used, and not the others.

So, I guess the setting to default need to go to that particular "main" view. Looks like I can not use HiddenFor in the sub-view, and then Html.Hidden in the main.

Is there a way to check in the sub-view which is the outer view?

Community
  • 1
  • 1
Sunny Milenov
  • 21,990
  • 6
  • 80
  • 106

4 Answers4

74

If I understand correct you will have something like this:

<input value="default" id="sth" name="sth" type="hidden">

And to get it you have to write:

@Html.HiddenFor(m => m.sth, new { Value = "default" })

for Strongly-typed view.

Piotr Czyż
  • 2,702
  • 2
  • 21
  • 15
  • 7
    One downside to `HiddenFor` vs `Hidden` is that `HiddenFor` includes validation strings in the output (e.g. a `data-val-required` and/or `data-val-number` attribute).... even though it is a hidden field. – iCollect.it Ltd Jul 09 '13 at 16:08
  • 16
    it appears that 'value' must be capitalized 'Value' – afreeland Oct 15 '13 at 15:06
40

There is a Hidden helper alongside HiddenFor which lets you set the value.

@Html.Hidden("RequiredProperty", "default")

EDIT Based on the edit you've made to the question, you could do this, but I believe you're moving into territory where it will be cheaper and more effective, in the long run, to fight for making the code change. As has been said, even by yourself, the controller or view model should be setting the default.

This code:

<ul>
@{
        var stacks = new System.Diagnostics.StackTrace().GetFrames();
        foreach (var frame in stacks)
        {
            <li>@frame.GetMethod().Name - @frame.GetMethod().DeclaringType</li>
        }
}
</ul>

Will give output like this:

Execute - ASP._Page_Views_ViewDirectoryX__SubView_cshtml
ExecutePageHierarchy - System.Web.WebPages.WebPageBase
ExecutePageHierarchy - System.Web.Mvc.WebViewPage
ExecutePageHierarchy - System.Web.WebPages.WebPageBase
RenderView - System.Web.Mvc.RazorView
Render - System.Web.Mvc.BuildManagerCompiledView
RenderPartialInternal - System.Web.Mvc.HtmlHelper
RenderPartial - System.Web.Mvc.Html.RenderPartialExtensions
Execute - ASP._Page_Views_ViewDirectoryY__MainView_cshtml

So assuming the MVC framework will always go through the same stack, you can grab var frame = stacks[8]; and use the declaring type to determine who your parent view is, and then use that determination to set (or not) the default value. You could also walk the stack instead of directly grabbing [8] which would be safer but even less efficient.

David Ruttka
  • 14,269
  • 2
  • 44
  • 39
  • works ... but I did not explain the real situation well. Editing the question, pls review. Thanks – Sunny Milenov Jun 29 '11 at 13:36
  • @Sunny see edit, but please only use this in your emergency case where you're trying to spare a code change / deployment – David Ruttka Jun 29 '11 at 14:40
  • Wow, thanks. I ended up using jQuery just after the @Html.Partial to set the fields by ID. Ugly, but works :) – Sunny Milenov Jun 29 '11 at 17:43
  • @Sunny That should be fine if you are requiring that all users of your site enable JavaScript. If that is not something you are requiring of your users, you should find a way that all features work properly even when JavaScript is disabled. – David Ruttka Jun 29 '11 at 17:47
  • `Hidden` gives a more lightweight output compared to `HiddenFor` as well. `HiddenFor` can include multiple validation strings in the output, even though it is hidden and they will not be used. – iCollect.it Ltd Jul 09 '13 at 16:10
12

While I would have gone with Piotr's answer (because it's all in one line), I was surprised that your sample is closer to your solution than you think. From what you have, you simply assign the model value before you use the Html helper method.

@{Model.RequiredProperty = "default";}
@Html.HiddenFor(model => model.RequiredProperty)
AmiNadimi
  • 5,129
  • 3
  • 39
  • 55
alans
  • 1,022
  • 9
  • 17
0

How about like this

public static MvcHtmlString HiddenFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, object htmlAttributes)
    {
        return HiddenFor(htmlHelper, expression, value, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    }

    public static MvcHtmlString HiddenFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, IDictionary<string, object> htmlAttributes)
    {
        return htmlHelper.Hidden(ExpressionHelper.GetExpressionText(expression), value, htmlAttributes);
    }

Use it like this

 @Html.HiddenFor(customerId => reviewModel.CustomerId, Site.LoggedInCustomerId, null)
mimo
  • 937
  • 12
  • 19