Displayname Attribute VS Display Attribute

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:

Short Name Description

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



Leave a reply



Submit