displayname attribute vs display attribute
They both give you the same results but the key difference I see is that you cannot specify a ResourceType
in DisplayName
attribute. For an example in MVC 2, you had to subclass the DisplayName
attribute to provide resource via localization. Display
attribute (new in MVC3 and .NET4) supports ResourceType
overload as an "out of the box" property.
what is the advantage of DisplayName attribute than Display attribute?
Display
attribute should be preferred over DisplayName
attribute. The former one comes form DataAnnotations
namespace and exposes more properties than the later one, ie. ShortName, Prompt, GroupName, Order, Description, which are used by DataAnnotationsMetadataProvider
.
Most importantly, DisplayName
accepts only literals, while Display
accepts resource type and key, which can be used to provide translations using separate resource files (resx).
Difference between these 2 Display attributes?
Possible duplicate:
displayname attribute vs display attribute
DisplayName sets the DisplayName in the model metadata. For example:
[DisplayName("foo")]
public string MyProperty { get; set; }
and if you use in your view the following:
@Html.LabelFor(x => x.MyProperty)
it would generate:
<label for="MyProperty">foo</label>
Display does the same, but also allows you to set other metadata properties such as Name, Description
Why is the Display(Name = ) attribute ignored in one of my ViewModels while it seems to work in my other models in ASP.NET MVC5?
I think this is because your model is referencing the interface and not the class. @model MVCBierApplication.Interfaces.IPartialPropertySearch
change it to @model MVCBierApplication.Models.BeerNamePartialViewModel
mvc DisplayName or Display(Name=...) depending on another model property
It looks like this code would work for const Type only:
public enum MyEnum
{
First,
Second
}
public class LoginViewModel
{
const MyEnum En = MyEnum.First;
[Required]
[DataType(DataType.Password)]
[Display(Name = (En == MyEnum.First ? "Password" : "aaa"))]
public string Password { get; set; }
}
There should be possible second option with your own implementation of the DisplayName:
public enum MyEnum
{
First,
Second
}
public MyDisplayNameAttribute : DisplayNameAttribute
{
public MyDisplayNameAttribute (MyEnum en, string text1, string text2) : base (CorrectName (en, text1, text2))
{}
public static string CorrectName (MyEnum en, string text1, string text2)
{
return en == MyEnum.First ? text1 : text2;
}
}
public class LoginViewModel
{
const MyEnum En = MyEnum.First;
[Required]
[DataType(DataType.Password)]
[MyDisplayName(MyEnum.Second, "password1", "password2")]
public string Password { get; set; }
}
However I don't feel that the both solutions are better then adding some kind of label to your ViewModel
Set/Change Display(Name=) Attribute of a Property in Controller/ViewComponent
Extending on the comment I left, one way you could solve this is by having your BaseViewModel
being an abstract class and have concrete classes deriving from it. So UserViewModel
and AdminViewModel
. These two concrete classes would then be the models for both TableView
and TableManagentView
and would be responsible for telling the "outside world" how to label fields.
The base class has two main aspects (apart from your normal fields): An abstract Dictionary<string, string>
which will contain the labels and a method to get the label from the list: string GetLabel(string propName)
. So something like this:
public abstract class BaseViewModel
{
protected abstract Dictionary<string, string> Labels { get; }
public string UserComment { get; set; }
public string GetLabel(string propName)
{
if (!Labels.TryGetValue(propName, out var label))
throw new KeyNotFoundException($"Label not found for property name: {propName}");
return label;
}
}
Then you create the two deriving classes User
and Admin
:
public sealed class UserViewModel : BaseViewModel
{
protected override Dictionary<string, string> Labels => new Dictionary<string, string>
{
{ nameof(UserComment), "User label" }
};
}
public sealed class AdminViewModel : BaseViewModel
{
protected override Dictionary<string, string> Labels => new Dictionary<string, string>
{
{ nameof(UserComment), "Admin label" }
};
}
They only implement the Dictionary<string, string>
and set the appropriate text for each field on the base class.
Next, changing your BaseViewComponent
to this:
View:
@model DisplayNameTest.Models.BaseViewModel
<h3>Hello from my View Component</h3>
<!-- Gets the label via the method on the base class -->
<p>@Model.GetLabel(nameof(BaseViewModel.UserComment))</p>
<p>@Model.UserComment)</p>
ComponentView class (simpler now)
public IViewComponentResult Invoke(BaseViewModel viewModel)
{
return View(viewModel);
}
Finally, changing your views TableView
and TableManagentView
to this:
@model WebApp.Models.AdminViewModel
@{
Layout = null;
}
<h1>Admin View</h1>
<div>
@await Component.InvokeAsync("Base", Model)
</div>
and the Controller to:
public IActionResult Index()
{
var adminViewModel = new AdminViewModel { UserComment = "some comment from admin" };
return View(adminViewModel);
}
Now when you navigate to TableView
, you'll pass a UserViewModel
to the BaseViewComponent
and it will figure it out the correct label. Introducing new fields will just now require you to change your viewmodels, adding a new entry to the Dictionary.
It's not perfect, but I think it's an okay way to solve it. I'm by far not an MVC expert so maybe others can come up with a more natural way to do it as well. I also prepared a working sample app and pushed to GitHub. You can check it out here: aspnet-view-component-demo. Hope it helps somehow.
WCF showing DisplayAttribute or DisplayName from DataMember
I want the descriptive name to show on the form I've created based on the WCF Service. How can I do that?
You can't.
The attributes are read by the serializer, but they are defined in your service assembly. What gets sent to the client depends on the binding used, but in for example a SOAP message (*HttpBinding) you will need the [DataMember(Name = "Foo")]
attribute, because that causes the serializer to alter the name of the element in the XML.
You'll have to apply the appropriate attribute to the class in the client proxy.
The alternative would be to tick Reuse Types
when generating the reference; then your client will use the classes from the same assembly the service uses, and so the attributes will be accessible in the client.
DisplayName attribute from Resources?
How about writing a custom attribute:
public class LocalizedDisplayNameAttribute: DisplayNameAttribute
{
public LocalizedDisplayNameAttribute(string resourceId)
: base(GetMessageFromResource(resourceId))
{ }
private static string GetMessageFromResource(string resourceId)
{
// TODO: Return the string from the resource file
}
}
which could be used like this:
public class MyModel
{
[Required]
[LocalizedDisplayName("labelForName")]
public string Name { get; set; }
}
ShortName in the Display attribute (DataAnnotations)
If you look at the Description for the ShortName
property on the Display
Attribute you'll see that it has a pretty limited scope out of the box:
Of course, that doesn't limit you from leveraging that value on your Model Metadata, but there aren't any native helpers that do so.
Starting with MVC 2, ModelMetadata
provides two methods to access the underlying data: FromStringExpression
and FromLambdaExpression
, so you don't really need to start from scratch in writing your own helper or extension method.
If you hate writing HTML helper methods, you can do this all inline:
@ModelMetadata.FromLambdaExpression<RegisterModel, string>(
model => model.TransferDate, ViewData).ShortDisplayName} )
But it's also perfectly valid to add an extension method for consistency of access, deduplication of code, and improved error handling
public static class MvcHtmlHelpers
{
public static MvcHtmlString ShortNameFor<TModel, TValue>(this HtmlHelper<TModel> self,
Expression<Func<TModel, TValue>> expression)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, self.ViewData);
var name = metadata.ShortDisplayName ?? metadata.DisplayName ?? metadata.PropertyName;
return MvcHtmlString.Create(string.Format(@"<span>{0}</span>", name));
}
}
And then use like any other helper method:
@Html.ShortNameFor(model => model.TransferDate)
Further Reading:
- How do I display the DisplayAttribute.Description attribute value?
- MVC has long subsisted on custom extension methods, like needing DisplayNameFor before it was added in MVC 4
- See this question for a quick breakdown of the differences between
[Display(name="")]
vs.[DisplayName("")]
attributes - See this answer for working with ASP.NET MVC 6 / Core 1
Related Topics
When to Use Ilist and When to Use List
Passing an Enum Value as Command Parameter from Xaml
Difference Between Char.Isdigit() and Char.Isnumber() in C#
Populate Treeview with File System Directory Structure
How to Get Urls of Open Pages from Chrome and Firefox
Restore a Minimized Window of Another Application
Grab All Text from HTML with HTML Agility Pack
Calling Generic Method with Type Variable
Getting All Controllers and Actions Names in C#
Convert File Path to a File Uri
Variables Within App.Config/Web.Config
How to Enumerate Through a Jobject
Fluent API, Many-To-Many in Entity Framework Core