Customising data annotations in dynamic data - asp.net

I have come across a scenerio that to customize DataAnnotations in Dynamic Data Web Application. This is the scenerio:
[Display(Name="DispName")]
public string DName{get;set;}
Instead of hardcoding Name="DispName" for Display DataAnnotation, I want to fetch some value from DataBase and fit int the Name attribute. like:
[Display(Name=SomeValueFromDB)]
public string DName{get;set;}
Is there any way to show the Name attribute of Display DataAnnotation from database instead of hardcoding its value?
Thanks in advance,
Sujith

I found a solution. But this is applicable only if we build the application:
Create a custom class (Say: CustomDisplayNameAttribute ) which inherits DisplayNameAttribute. And call that class name as display attribute (here "CustomDisplayName") above the property name.
While setting DataAnnotation for Display attribute, omit that "Attribute" part from the class name. ie. the DataAnnotation for Display attribute will be CustomDisplayName (not CustomDisplayNameAttribute).
public class DomainClass
{
[CustomDisplayName("")]
public object PropertyName{ get; set; }
}
public class CustomDisplayNameAttribute : DisplayNameAttribute
{
public CustomDisplayNameAttribute(string value)
: base(GetMessageFromResource(value))
{ }
private static string GetMessageFromResource(string value)
{
return "Custom Display Name";
}
}
Hope this helps all....
Happy Coding....

Related

How to add a per element validation for en Enumerable in Asp.Net Core?

I have this field that will be mapped from body:
[Required]
public IReadOnlyCollection<long?> Ids { get; set; }
I'd like to add a required attribute (or rather any arbitrary validation attribute) to the element itself (i.e. I want every element of the array validated).
I could create a class that would have an Id, but then I'll need to pass an array of objects from JSON while I'd like ideally to get an array like that [1,2,3,4].
Is it possible to do with some trick, I did not manage to figure it out?
You can create a custom attribute which will check for non nulls on an IEnumerable:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)]
sealed public class NonNullElementsAttribute : ValidationAttribute{
public override bool IsValid(object value)
{
// cast object to IEnumerable
// Validate your logic.
}
}
You can the put this property on top of your element
[Required]
[NonNullElements]
public IReadOnlyCollection<long?> Ids { get; set; }
You can make this even more generic by making it a more generic check on list that validates each element. For example for string types you may want string.IsNullOrWhiteSpace

When to use BindAttribute?

I'm learning asp.net mvc and wonder when we need to use BindAttribute.
The first case (using Bind):
Model:
public class Book
{
public string Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
}
Controller:
public IActionResult Create([Bind(nameof(Book.Name), nameof(Book.Author))] Book model)
{
return Ok();
}
The book Id would be generated on server side. So, client side has nothing to do with it, every actions try to change/make the id is prevented.
The second case (not using Bind):
Model:
public class BookViewModel
{
public string Name { get; set; }
public string Author { get; set; }
}
Controller:
public IActionResult Create(BookViewModel model)
{
return Ok();
}
Because the second model doesn't contain Id property, we don't need to prevent from creating or changing.
I prefer the second. It's easy to manage model.
Is there a case we must use Bind attribute?
We use bind when we want that some properties of complex property are ignored when received on server. It could be for safety or other reasons.
When this action is executed the MVC model binder will use the request parameters to populate the user parameter's properties, as you may already know. However, the Bind attribute tells the model binder to only populate properties with names specified.
So in this case only the Username, FullName and Email properties will be populated. All others will be ignored.
See here for more details: http://ittecture.wordpress.com/2009/05/01/tip-of-the-day-199-asp-net-mvc-defining-model-binding-explicitly/
If you have situation when you only have to ignore one parametar from binding you could use Exclude property:
[Exclude]
public Entity Name {get; set;}
Bind is used to increase security and unauthorized data to be posted on server . In your model class , suppose you have content property also. if the content property is not needed in the future. Then it would be difficult for you to remove all the occurrences of that property. Here you can use bind property like this
[Bind(exclude="content")]
or you can bind only selected properties to be posted on server by including the properties like this
public ActionResult create([Bind(Include = "Name,Author")] Modelclass modelclass)
{
//Do something here
}
You can learn more about it here
Second approach is more suitable instead writing all the properties and bind them but there are some situations where you must bind user like you have a roles property or IsAdmin property in your model then you might not want that user somehow posts the IsAdmin or roles properties to the server . That's where you can use Bind attribute

How to use a class to create the SQLite table and ignore the fact that it is a List<ChildrenObjectModel>?

I'm using a class to generate an SQLite table, but I also want to use it as ItemSource for a two levels ListView (A listview with sub items).
This works for the ListView:
public class ParentModel:List<ChildrenModel>
{
[PrimaryKey]
public string uid { get; set; }
public string name { get; set; }
[Ignore]
public string attributeA { get; set; }
public ParentModel() {
}
}
But when I do mySQLiteConnection.CreateTable<ParentModel>(); it throws an Exception because the Object is a List<>.
I can [Ignore] attributes, but is there a way to ignore the fact that the the class is a List<>?
I can also create a List variable inside the model and [Ignore] it, but this wouldn't work for the ListView.
The only solution I can think is creating two classes with the same attributes, one being a List<> and the other one not.
But I really don't like this idea.
Not sure why you want to inherit from List<ChildrenModel>. You should make the ChildrenModel class a class that can create a table, and then that table would have all of the ChildrenModel items. Then in ParentModel you could have a public property of type List<ChildrenModel> which you can load from the ChildrenModel table. You would want to ignore that property as SQLite can not store a List. You can then access your populated List through the public property for the List<ChildrenModel> in the ParentModel class. That's what I would do anyway.

How to do localization for contents coming from #Html.LabelFor() in mvc3

I am just extending my this question a bit.
I have my App_LocalResources in my MVC web application (I don't have it in separate dll).
I have a my Model in different assembly. In the Model I have 2 classes Country and City:
public class Country: MyContainer
{
public City city {get;set;}
}
public class City
{
public CityName {get;set;}
}
public class MyContainer
{
public Cid {get;set;}
}
So in my action method I create and pass an object of country as my viewmodel.
And in the view I use this:
#Html.LabelFor(mdl=>mdl.City.CityName)
#Html.LabelFor(mdl=>mdl.Cid)
So this works well and label with text are rendered in English.
But how do I modify this so that it reads the text from my Resource files in my web application?
You could write a custom display attribute:
public class LocalizedDisplayNameAttribute : DisplayNameAttribute
{
public LocalizedDisplayNameAttribute(string key): base(FormatMessage(key))
{
}
private static string FormatMessage(string key)
{
// TODO: fetch the corresponding string from your resource file
throw new NotImplementedException();
}
}
and then:
public class City
{
[LocalizedDisplayName("cityname")]
public string CityName { get; set; }
}
You may also checkout the following localization guide. It provides a full implementation of a sample attribute.
You can use [Display(ResourceType = typeof(App_LocalResources), Name = "AgreeTandCs")] where App_LocalResources is the name of the resource class (your .resx) and Name is the name of the static string you want to reference. Use LabelFor as usual in your view, and it will automagically pull in your resource.
In my example, the label displays the string stored with the variable name AgreeTandCs, and if you're viewing it in English it will be shown in the page as "I agree to these Terms and Conditions".
You can also use translation with {0}, {2} parameters inside translation string.
He is my example Localize Compare attribute

Overriding validation attribute from a base Model

i have a MVC controller called MyController with an action called MyAction. For other hand i have a Model called MyModel, and all this classes are in a project called Portal.Website (Asp.net MVC3 Application) that i use as a generic website and that store common functionalities for custom websites that i will add in the future.
For other hand i have another website project with a reference to Portal.Website project called Portal.Website.MyCustomWebsite.
This is the viewmodel MyModel.cs in the generic website part:
namespace Portal.Website
{
public class MyModel
{
[Required(ErrorMessage="The field Name is required.")]
[Display("MyPropertyOriginal")]
public virtual string Name{get;set;}
}
}
This is the controller and action in the generic website part:
namespace Portal.Website
{
public class MyController: Controller
{
[HttpPost]
public ActionResult MyAction(MyModel model)
{
if(Model.IsValid)
....
//My issue: Im getting the error message in english, not the overridden one.
}
}
}
This is the viewmodel that i created in the custom part:
namespace Portal.Website.MyCustomWebsite
{
public class MyModel: MyModel
{
[Required(ErrorMessage="My error message in other language.")]
[Display("MyPropertyOverriden")]
public override string Name{get;set;}
}
}
My problem:
I would like to override the ErrorMessage of the Required attribute. For this reason i created a new Model in my custom project. For other hand i would like to use the Controller/Action (MyController/MyAction) that is already defined in my common part.
Do you know if this is possible? Im only getting the issue with the Required attribute, but with the Display one its working perfect.
Thanks in advance.
Greets.
Jose.
You may want to check out this article that suggests two possible solutions :
http://www.codeproject.com/Articles/130586/Simplified-localization-for-DataAnnotations
I've found it was making more sense to re-create some DataAnnotation classes with my custom logic.
MVC3 comes with better support for I18N (internationalisation) than it's predecessors - you can pass the RequiredAttribute the type of your resource class and the resource key and the error message will be displayed in whichever language is most appropriate:
[Required(ErrorMessageResourceType = typeof(MyResources), ErrorMessageResourceName = "ResourceKey")]
public override string Name { get; set; }

Resources