Custom Data Annotation attribute bool check - asp.net

I am trying to make a custom data annotation attribute with a simple bool result, if the property have the data annotation, then perform an action. My objective is to make an array with all the properties that have the Filter dataanotation to later make a DropDownListFor in view with that information.
public class Foo
{
public string property1 { get; set; }
[Filter]
public string property2 { get; set; }
}
Then somewhere in the code:
IList<PropertyInfo> properties = typeof(Foo).GetProperties().ToList();
ArrayList propertiesThatCanBeFiltered = new ArrayList();
foreach (var propertyInfo in properties)
{
if (propertyInfo.Attributes("Filter").Exists)
{
propertiesThatCanBeFiltered.Add(propertyInfo.Name);
}
}

You need GetCustomAttribute<T> Documentation
And here how to apply it:
IList<PropertyInfo> properties = typeof(Foo).GetProperties().ToList();
ArrayList propertiesThatCanBeFiltered = new ArrayList();
foreach (var propertyInfo in properties)
{
var filterAttribute = propertyInfo.GetCustomAttribute<Filter>();
if (filterAttribute != null)
{
propertiesThatCanBeFiltered.Add(propertyInfo.Name);
}
}

I believe custom ActionFilters is what you are after:
http://msdn.microsoft.com/en-us/library/dd410056(v=vs.100).aspx
This is what you are stating in your question where when a certain attribute is applied to then execute some logic... AF's does just that.
Other than that, there is a way to create your own custom data annotation:
How to create Custom Data Annotation Validators
http://weblogs.asp.net/brijmohan/asp-net-mvc-3-custom-validation-using-data-annotations
but it depends exactly what you want to do. Do not get the 2 mixed up together.

Related

.NET CORE List properties of an attribute

I have multiple classes that use this custom attribute. All of them implement the same interface and they all have this custom attribute and have different names
public class NameAttribute : Attribute
{
public NameAttribute(string name)
{
this.Name = name;
}
public string Name { get; }
}
Is there a way to return a list of these names in the controller?
I'll answer my own question for if someone has the same problem in the future. This is what I did:
IEnumerable<Type> types = typeof(Startup).Assembly.ExportedTypes
.Where(type => type.IsClass && !type.IsAbstract)
.Where(type => type.GetInterface("IName") != null)
.Where(type => type.GetCustomAttribute<NameAttribute>() != null);
List<string> rules = new List<string>();
foreach (Type t in types)
{
rules.Add(t.GetCustomAttribute<NameAttribute>().Name);
}
Basicly what happens is that I look for all the exported types that implement an interface named "IName" and have the "NameAttribute" attribute. This will return a enumerable list with types.
Next it is possible to retrieve the custom attribute and put the name in an arraylist.

Get entities by string in Entity Framework

I am trying to do some dynamic code using Entity Framework. I have a model (Model1) with one table(Test1), it's simple. What I'm trying to do is accessing the model Test1 programatically with the name of the table, to use it after in differents tasks. I was looking for in google and I have found Finding entities by key in entity framework but it's doesnt work, or I don't have any idea...
When I ran this code it breaks on trying to set entityProperty
Model1Container m = new Model1Container();
PropertyInfo entityProperty = m.GetType().GetProperties().Where(t => t.Name == "Test1").Single();
var baseQuery = (IQueryable<IIdentity>)entityProperty.GetValue(m, null);
Sorry for the explanation.
Any ideas?
You create an object with a string name and set its properties:
public class Test
{
//All my classes have these properties
//You can set up an interface and in the method you can set entity to an interface type
//You can even put these interfaces on edmx generated entities
//http://stackoverflow.com/questions/14059455/adding-validation-attributes-with-an-entity-framework-data-model
public string AString { get; set; }
public DateTime ADate { get; set; }
}
public class HomeController : Controller
{
public ActionResult IndexStackOverflow101()
{
Assembly assembly = Assembly.Load("Testy20161006");
Type t = assembly.GetType("Testy20161006.Controllers." + "Test");
Object entity = (Object)Activator.CreateInstance(t);
PropertyInfo entityProperty = t.GetProperty("AString");
PropertyInfo entityPropertyTwo = t.GetProperty("ADate");
entityProperty.SetValue(entity, Convert.ChangeType("ap", entityProperty.PropertyType), null);
entityPropertyTwo.SetValue(entity, Convert.ChangeType(DateTime.Now, entityPropertyTwo.PropertyType), null);

ASP.NET Core Custom Parameter Binding

I have a situation in which I would like to do custom parameter binding for an api controller in ASP.NET core.In WebAPI 2.0 it was possible to perform custom binding to primitive types by implementing various interfaces such as IValueProvider and providing a ValueProviderFactory. This does not seem the case with ASP.NET core in as far as what I understand from the documentation I found here.
I did notice this SO post which lead me to this article which overrides the behavior for the MutableObjectModelBinder. It would appear I could do something along those lines such as:
[HttpGet]
[Route("api/{domain}/[controller]")]
public IEnumerable<string> Get([ModelBinder(BinderType = typeof(MyCustomBinder))]string orderby)
{
//Do stuff here
}
This doesn't necessarily seem right to me since I am just dealing with a primitive type however I cannot seem to find any documentation for another way of doing this.
Create a binder provider class for your custom type
public class MyCustomBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.ModelType == typeof(MyCustom))
{
return new BinderTypeModelBinder(typeof(MyCustomBinder));
}
return null;
}
}
and register it in the services
services.AddMvc(c =>
{
c.ModelBinderProviders.Insert(0, new MyCustomBinderProvider());
});
And the custom binder can go like
public class MyCustomBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext.ModelType != typeof(MyCustom))
{
return TaskCache.CompletedTask;
}
var parameters = new Dictionary<string, string>();
foreach (var parameter in bindingContext.ModelType.GetProperties())
{
var valueProviderResult = bindingContext.ValueProvider.GetValue(parameter.Name);
if (valueProviderResult.FirstValue != null)
{
parameters.Add(parameter.Name, valueProviderResult.FirstValue);
}
}
var result = Activator.CreateInstance(bindingContext.ModelType);
//write your custom code to map the result with the parameters
bindingContext.Result = ModelBindingResult.Success(result);
return TaskCache.CompletedTask;
}
}
Your custom type class
[ModelBinder(BinderType = typeof(MyCustomBinder))]
public class MyCustom
{
public int Page { get; set; }
public int Rows { get; set; }
}
and your controller can take the custom class as query string parameter
[HttpGet("data")]
public DataTransferObject GetData(MyCustom query)
{
}
Migrating OP's solution from the question to an answer, with meta commentary trimmed:
I just decided to go with a helper class to parse the parameter due to having to meet deadlines.

How to get the elements from a generic List<T> in C#? [duplicate]

This question already has answers here:
Convert generic List/Enumerable to DataTable?
(28 answers)
Closed 8 years ago.
I have a class that converts a T List into a DataTable. And my problem is that I can not get the elements from the generic List T. T can be any model from entityFramework, like:
public class Test
{
public string userId { get; set; }
public string email { get; set; }
public string name { get; set; }
}
So List T is equivalent to List Test
My code is:
public class ConvertListToDataTable<T>
{
public T Field;
public DataTable ConvertTest<T>(List<T> item)
{
DataTable dT = new DataTable();
foreach(T t in item)
{
// here I want to get the elements from T and put them into the DataTable
}
return dT;
}
}
I know how to procces the dataTable, but I don't know how to get the 'userId', 'email', 'name' from the list
The reason why you cannot access just any property from an object of type T is because T could be literally anything - from a generics standpoint how can you know upfront what properties type T has?
If you happen to know that all objects are based on a common interface or base class then you could apply a generic constraint to your ConvertListToDataTable<T> class; this would allow the compiler to know upfront that some properties are available to that type at a base level.
But if you want to allow T to be any type at all then #MrFox is correct in that you would need to use Reflection to view the properties the type has at runtime and fill your DataTable that way.
Reflection can solve this:
public void Test(object t)
{
var properties = t.GetType().GetProperties();
foreach (var p in properties)
{
dT.Columns.Add(new DataColumn(p.Name, p.PropertyType));
}
var row = dT.NewRow();
int col = 0;
foreach (var p in properties)
{
row[col++] = p.GetValue(t);
}
}
You can give the GetProperties method arguments if you only want properties of a certain type.

asp.net mvc custom attributes

I am trying to create a custom attribute in mvc to use it's parameters in a view as breadCrumb.
well, this is the code of the attribute
[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class BreadCrumbAttribute : Attribute {
public BreadCrumbAttribute(string title, string parent, string url) {
this._title = title;
this._parent = parent;
this._url = url;
}
#region named parameters properties
private string _title;
public string Title {
get { return _title; }
}
private string _url;
public string Url {
get { return _url; }
}
private string _parent;
public string Parent {
get { return _parent; }
}
#endregion
#region positional parameters properties
public string Comments { get; set; }
#endregion
}
this is the call of the attribute
[BreadCrumbAttribute("tile", "parent name", "url")]
public ActionResult Index() {
//code goes here
}
this is a way of how I'd like to get the values. (this is a partial view)
System.Reflection.MemberInfo inf = typeof(ProductsController);
object[] attributes;
attributes = inf.GetCustomAttributes(typeof(BreadCrumbAttribute), false);
foreach (Object attribute in attributes) {
var bca = (BreadCrumbAttribute)attribute;
Response.Write(string.Format("{0}><a href={1}>{2}</a>", bca.Parent, bca.Url, bca.Title));
}
Unfortunately, the attribute didn't get call with the way I implement it. Although, If I add the attribute in Class instead of an Action method it worked.
How could I make it work?
Thanks
The problem is that you are using reflection to get the attributes for the class, so naturally it does not include attributes defined on the action method.
To get those, you should define an ActionFilterAttribute, and in the OnActionExecuting or OnActionExecuted method, you can use filterContext.ActionDescriptor.GetCustomAttributes() method (MSDN description here).
Note that with this solution, you will likely have two different types of attributes: The first one is the one you wrote, to define the breadcrumbs. The second is the one that looks at the attributes on the executing action and builds up the breadcrumb (and presumably adds it to the ViewModel or sticks it in HttpContext.Items or something).

Resources