I have an ASP.NET MVC2 application. On one of my pages I have a textbox defined in the following manner:
<%: Html.TextBoxFor(model => model.PostCode) %>
Which is working perfectly.
However, for specific countries (model.Country) I do not want to show this TextBox.
What is the best way of implementing this?
This is an .aspx file, not .cshtml
Thanks
Create a property in your model class, and try this:
#if (!Model.IsSpecificCountry) {
#Html.TextBoxFor(model => model.PostCode)
}
Update:
<%if (!Model.IsSpecificCountry) { %>
<%= Html.TextBoxFor(model => model.PostCode) %>
<% } %>
Related
As part of my current project I've blundered into an enormous MVC web form that I know relatively little about, and am having to do some fairly serious debugging on it. I have plenty of WebForms experience but little with MVC so please forgive me if the following isn't clear, or is asking silly questions.
Part of the form is a custom .ascx control which gets information from another URL and limits what the user can put into that section of the form based on that information. All the form elements can be turned on and off. If you turn this particular form element on, fill it in and submit then the ModelState fails its validation check, complaining that its missing a required value. The form is returned with the problematic element switched on, but no values in the boxes. If you don't switch on this particular element, the ModelState validates properly.
I know enough about MVC to understand that the mapping between form elements and the model occurs under the hood. However this makes it very difficult to debug. I really have no idea what the problem is or, worse, how to go about investigating what the cause is. Any suggestions on either front would be greatly appreciated.
EDIT: Some code
//start to deal with specialist form user controls
case "ViewData.Customer.CustomFieldTypes.BlackWhiteListConfigViewData ":
if (Model.Visible)
{ %>
<div class="formItem">
<label>
<% Html.RenderPartial("~/Views/Shared/EditorTemplates/BlackWhiteListConfigViewData.ascx"); %>
</div>
<% }
else
{ %>
<%= Html.HiddenFor(m => Model.Value) %>
<% }
b break;
And the binding code:
switch (fieldType)
{
case FeatureFieldFactory.BlackWhiteListConfigElTypeName:
{
// create a new default model binder, and tell it which type we actually want it to bind.
BlackWhiteListConfigViewData model = new BlackWhiteListConfigViewData();
bindingContext.ModelMetadata =
ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(BlackWhiteListConfigViewData));
return base.BindModel(controllerContext, bindingContext);
}
EDIT: BlackWhiteListConfigViewData.ascx code
if (Model.Visible)
{ %>
<script type="text/javascript">
$(cpContext.CurrentService()).bind('onServiceAttributesReady', function (context) {
$(document).ready(function () {
$("#js-hook-BlackWhiteListLoading").hide();
if (context.target.AttributeNames().length === 0) {
$("#js-hook-AddBlackWhiteListEntry").hide();
$("#js-hook-BlackWhiteListConfigTable").hide();
$("#js-hook-BlackWhiteListMessage").html('There are no attribute types present in the catalogue. The Black and White lists can be configured once the catalogue is loaded.');
$("#js-hook-BlackWhiteListMessage").show();
}
else {
$("#js-hook-BlackWhiteListMessage").hide();
$("#js-hook-AddBlackWhiteListEntry").show();
$("#js-hook-BlackWhiteListConfigTable").show();
}
});
});
$(cpContext.CurrentService()).bind('onServiceAttributesError', function (context) {
$(document).ready(function () {
$("#js-hook-BlackWhiteListLoading").hide();
$("#js-hook-AddBlackWhiteListEntry").hide();
$("#js-hook-BlackWhiteListConfigTable").hide();
$("#js-hook-BlackWhiteListMessage").html('No attribute types retrieved from service API. The Black and White lists can be configured when a Build has been completed and service API is accessible.');
$("#js-hook-BlackWhiteListMessage").show();
});
});
cpContext.CurrentService().getAttributes();
</script>
<div class="formItem narrow blackWhiteListConfig">
<% using (Html.BeginCollectionItem("fields"))
{
Model.Value = "n/a";
%>
<%= Html.HiddenFor(m => Model.Id) %>
<%= Html.HiddenFor(m => Model.Type) %>
<%= Html.HiddenFor(m => Model.Name) %>
<%= Html.HiddenFor(m => Model.Visible) %>
<%= Html.HiddenFor(m => Model.DisplayName) %>
<%= Html.HiddenFor(m => Model.Value) %>
<table id="js-hook-BlackWhiteListConfigTable" class="configTable" style="display:none">
<thead>
<tr><th class="configTableColumn">Key Attribute Type</th><th class="configTableColumn">Key Value</th><th class="transparent"></th><th class="configTableColumn">Related Attribute Type</th><th class="configTableColumn">Related Attribute Value</th><th class="configTableColumn narrow">Black</th><th class="configTableColumn narrow">White</th><th class="transparent" style="width:20px"></th></tr>
</thead>
<tbody class="blackWhiteListRows">
<% foreach (BlackWhiteListEntryViewData entry in Model.Entries)
{ %>
<%= Html.EditorForNested(e => entry) %>
<% } %>
</tbody>
</table>
<hr />
<p id="js-hook-AddBlackWhiteListEntry" class="clear" style="display:none">Add another entry</p>
<p id="js-hook-BlackWhiteListMessage" class="clear" style="display:none">There are no attribute types present in the catalogue. The Black and White lists can be configured once the catalogue is loaded.</p>
<img id="js-hook-BlackWhiteListLoading" src="<%=Links.Content.images.content_loading_gif %>" alt="Loading Black and White list configuration..."
style="" class="clear" />
<%= Html.ValidationMessageFor(m => Model) %>
<% } %>
Model.Value) %>
Cheers,
Matt
Try replacing:
<% Html.RenderPartial("~/Views/Shared/EditorTemplates/BlackWhiteListConfigViewData.ascx"); %>
with:
<%= Html.EditorForModel() %>
or if your model type is not BlackWhiteListConfigViewData you could specify it:
<%= Html.EditorForModel("BlackWhiteListConfigViewData") %>
Also inside your editor template you seem to be using some custom helpers such as Html.EditorForNested. Make sure your input field names respect the conventions for binding to a list.
I know how to show a link on an MVCContrib Grid column by using Html.ActionLink, but what I want to do is to base on the value of a field where if the field has a value = false then show text and if it has true then show a link.
It won't let me do something like this:
column.For(x => x.HasValue == false ?
x.Name : Html.ActionLink(x.Name, "MyMethod", "MyController")
"cannot convert lambda expression to type 'string' becasue it is not a delegate type"
It lets me use Html.Raw for both conditions but when I run the app, I get the same error message
Thanks in advance.
In ASP.NET MVC 2 you could use the Action Syntax:
column.For("Name")
.Named("")
.Action(item => { %>
<td style="font-weight:bold">
<% if (item.HasValue) { %>
<%= Html.Encode(item.Name) %>
<% } else { %>
<%= Html.ActionLink(item.Name, "MyMethod", "MyController") %>
<% } %>
</td>
<% });
As an alternative you could also use a partial:
column
.For("Name")
.Named("")
.Partial("MyPartial");
and inside MyPartial.ascx perform the test.
In ASP.NET MVC 3 this has been deprecated in favor of custom columns (columns.Custom(...)).
Code:
<% foreach (var item in Model) { %>
<td>
<%= Html.Encode(item.BirthDate) %>
</td>
<% } %>
display this: 8/24/2009 12:00:00 AM but I need only date (8/24/2009). It is possible to do without any formating in controller action
There are a couple of ways to go about it. If you're using MVC 2, you could use a DisplayTemplate. Just put a DateTime.ascx file in the folder called /Views/Shared/DisplayTemplates and the line of code it would have in it is:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %>
<%: Model.HasValue ? Model.Value.ToShortDateString() : string.Empty %>
(Note: if you use the <%: syntax then you don't need the Html.Encode() because <%: does the HTML encoding for you - but that's only if you're using VS2010. If you're using MVC 2 with VS2008, then stick with the Html.Encode() for this part) Then in your view you would simply do this:
<%: Html.DisplayFor(m => m.BirthDate) %>
That will change the format to only have the Date for all DateTime's in your application. Of course you could put that directly in the view as well. But the DisplayTemplate will change it for all other DateTime's as well and you won't have to concern yourself with it in the view since it happens for your automatically.
If BirthDate is string datatype
<%= Html.Encode(!String.IsNullOrEmpty(item.BirthDate) ?
Convert.ToDateTime(item.BirthDate).ToShortDateString() : item.BirthDate) %>
If BirthDate is datetime datatype
<%=Html.Encode(String.Format("{0:MM/dd/yyyy}", item.BirthDate))%>
I would say that formatting is a responsibility of the view, not the controller, so format the output like this:
<% foreach (var item in Model) { %>
<td>
<%= Html.Encode(item.BirthDate.ToShortDateString() %>
</td>
<% } %>
If item.BirthDate is type of DateTime you can use ToShortDateString() method:
item.BirthDate.ToShortDateString();
<% foreach (var item in Model) { %>
<td>
<%= Html.Encode(item.BirthDate.ToString("MM/dd/yyyy")) %>
</td>
<% } %>
The ViewUserControl below results in the following error at runtime:
The Collection template was used with an object of type 'System.Data.Entity.DynamicProxies.Collection_1D9779ACB92AE24E3428C288EA7B1480A6477CF8861FB7582692E775613EFB3A', which does not implement System.IEnumerable.
The error occures on this line: <%: Html.EditorFor(model => model) %>
If I change the name of the model object to Collection2 it works. Does it gets confused because Collection is also the name of an object in the .net framework?
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<CollectionManager.Models.Collection>" %>
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm()) { %>
<%: Html.ValidationSummary(true) %>
<%: Html.EditorFor(model => model) %>
<input type="submit" value="Save" />
<% } %>
remco - yes, i think that would definately be a reserved word. not sure about it getting confused but definately you should take care with naming when potential clashes could occur. the same thing is true of variable names, tho you can prefix them with # to override that i.e. string #absract would be allowable, whereas string abstract wouldn't.
go with the 'reserved' flow :)
jim
I have a View that contains a usercontrol. The usercontrol is rendered using:
<% Html.RenderPartial("GeneralStuff", Model.General, ViewData); %>
My problem is that the usercontrol renders nicely with values from the model but when I post values edited in the usercontrol they are not mapped back to Model.General. I know I can find the values in Request.Form but I really thought that MVC would manage to map these values back to the model.
My usercontrol:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<namespace.Models.GeneralViewModel>" %>
<fieldset>
<div>
<%= Html.LabelFor(model => model.Value)%>
<%= Html.TextBoxFor(model => model.Value)%>
</div>
</fieldset>
I'm using .Net MVC 2
Thanks for any help!
Problem solved!
My usercontrol is rendered with:
<%= Html.EditorFor(model => model.General); %>
My model looks like this:
public class TestEditViewModel
{
[UIHint("GeneralViewModel")]
public GeneralViewModel General { get; set; }
}
And my usercontrol is placed under Views->Shared->EditorTemplates and named "GeneralViewModel.ascx"