Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[MVC 5] Scaffolding templates - property attributes lezen

Pagina: 1
Acties:

  • NickThissen
  • Registratie: November 2007
  • Laatst online: 18-11 13:07
Ik ben bezig met een MVC 5 project waarbij ik de view scaffolding templates heb aangepast door middel van t4 text templates.

Ik zou graag custom attributes toevoegen aan mijn model properties die ik dan kan uitlezen in de t4 template en aan de hand daarvan kan bepalen wat voor code er in de view moet komen.

Bijvoorbeeld, mijn model is dit:
C#:
1
2
3
4
5
6
7
8
public class Team
{
    [Key]
    public int Id {get; set;}
    
    [CustomAttribute(Bold = true)]
    public string Name {get; set;}  
}



In de t4 template van de List view (de Index view dus) zit bijvoorbeeld dit stukje om de tabel headers te genereren:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<#
IEnumerable<PropertyMetadata> properties = ModelMetadata.Properties;
foreach (PropertyMetadata property in properties) {
    if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey) {
#>
<#
        // This is a temporary work around until core scaffolding provides support for independent associations.
        if (property.IsAssociation && GetRelatedModelMetadata(property) == null) {
            continue;
        }
#>
        <th>
            @Html.DisplayNameFor(model => model.<#= GetValueExpression(property) #>)
        </th>
<#
    }
}
#>


Dit gooit dus eigenlijk voor elke relevante property dit stukje code in de view:
code:
1
2
3
<th>
            @Html.DisplayNameFor(model => model.<property naam>)
        </th>

(waarbij <property naam> dus vervangen wordt)

In dit stukje zou ik graag willen weten of de property mijn CustomAttribute heeft en welke waarde die heeft, zodat ik kan beslissen wat ik er mee moet doen.


Heeft iemand enig idee hoe dit moet?

Mijn iRacing profiel


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Je kunt custom attributes opvragen met GetCustomAttribute().

Als je me 2 minuten geeft (moet 't even zoeken) dan post ik een handige helper-method.
Oh, wacht, dat zat gewoon in 't .Net framework 8)7

C#:
1
2
3
4
5
6
7
8
var att = typeof(MyType).GetCustomAttributes<MyAttribute>();

//Usage:
var att = typeof(MyType).GetCustomAttributes<MyAttribute>().FirstOrDefault();
if (att !=null && att.Bold)
{
    //...
}

[ Voor 45% gewijzigd door RobIII op 07-05-2014 17:14 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • NickThissen
  • Registratie: November 2007
  • Laatst online: 18-11 13:07
Ik weet hoe ik custom attributes van een Type haal, maar ik zie hier niet hoe ik aan dat Type kom. 'property' heeft type PropertyMetadata, en daar hoef ik de attributen niet van te hebben. Ik moet de attribute op een of andere manier uit de Metadata halen (of wellicht het type, Team in dit geval, uit de Metadata en dan de attributes van de property op naam zoeken ofzo).

Mijn iRacing profiel


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Moet je dan niet gewoon in ModelMetadata kijken i.p.v. PropertyMetadata? Die heeft namelijk gewoon weer een ModelType property. Vervolgens haal de alle members die je interesseren op:

C#:
1
2
3
4
5
6
7
8
var mytype = ModelMetadata.ModelType;

//We're only interested in properties and/or fields of a type
var onlythesemembers = new[] { MemberTypes.Field, MemberTypes.Property };

//Get all properties/fields having a MyAttribute attribute
var props = mytype.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)
                .Where(t => onlythesemembers.Contains(t.MemberType) && t.GetCustomAttribute<MyAttribute>() != null);

Stop dat in een dictionary/hashmap/whatevs en je kun je je foreach-loop kijken of een bepaalde property voorkomt in die dict/hashmap en daar dan weer wat mee doen.

[ Voor 86% gewijzigd door RobIII op 07-05-2014 17:43 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • NickThissen
  • Registratie: November 2007
  • Laatst online: 18-11 13:07
Ik dacht dat je het opgelost had, maar ik zie nu dat ModelData van type Microsoft.AspNet.Scaffolding.Core.Metadata.ModelMetadata is, en niet System.Web.Mvc.ModelMetadata waar je naar linkt :( En die heeft net geen ModelType property, voor zover ik kan zien geen manier om de model type te verkrijgen.


Edit
Ik zie dat ik wel de naam (string) van het model type kan krijgen via parameter "ViewDataTypeName", daar kan ik vast wat mee :)

[ Voor 14% gewijzigd door NickThissen op 07-05-2014 19:46 ]

Mijn iRacing profiel


  • NickThissen
  • Registratie: November 2007
  • Laatst online: 18-11 13:07
Eindelijk gelukt :) Het was nog niet zo makkelijk om het type te krijgen zelfs met de naam, omdat de text templating engine niet in de huidige assembly draait.

Dit was uiteindelijk nodig:
C#:
1
2
var typeName = Assembly.CreateQualifiedName("AcCtc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", ViewDataTypeName);
var modelType = Type.GetType(typeName);

Het hele gedoe met Version=1.0.0.0 etc zou in principe standaard moeten zijn en niet nodig hoeven zijn, maar blijkbaar bij T4 wel, zonder dat werkt het niet... Niet heel handig omdat dit zo kan veranderen, maar goed, het werkt nu...

Bedankt.

Mijn iRacing profiel


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik heb geen tijd (noch de middelen voorhanden) nu om 't uit te zoeken, maar dat moet makkelijker (en soliderderder :P ) kunnen...

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • NickThissen
  • Registratie: November 2007
  • Laatst online: 18-11 13:07
Eens, maar goed... ik kreeg het niet aan de praat.

Dit werkt allemaal niet
C#:
1
2
3
var modelType = Type.GetType("Team"); // alleen class name
var modelType = Type.GetType("AcCtc.Models.Team"); // plus namespace
var modelType = Type.GetType(Assembly.CreateQualifiedName("AcCtc", "AcCtc.Models.Team")) // AcCtc = assembly name


En ja ik heb (het t4 equivalent van) een 'using' statement in de template wat zowel de assembly als de relevante namespace importeert:
code:
1
2
<#@ assembly name="F:\Users\Nick\Dropbox\VS Projects\AcCtc\AcCtc\bin\AcCtc.dll" #>
<#@ import namespace="AcCtc.Models" #>


Deze zijn ook nodig om de CustomAttribute uberhaupt te kunnen gebruiken in de template uiteraard omdat die in dit project zit.

Het vreemde is dat ik wel gewoon een Team object kan maken, bijv;
C#:
1
var team = new Team();

dat gaat zonder problemen (zolang die imports erin zitten), maar Type.GetType("Team") werkt niet en geeft null 8)7

Dit is trouwens nog een vervelend iets want daar moet ik zelfs het absolute path naar de dll gebruiken, normaal kun je iets als $(SolutionDir) macros gebruiken maar dat werkt hier ook niet... Het is dus lang niet ideaal maar ik zie geen oplossing.

Mijn iRacing profiel


  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 09:34

Sebazzz

3dp

NickThissen schreef op woensdag 07 mei 2014 @ 21:38:
Het vreemde is dat ik wel gewoon een Team object kan maken, bijv;
C#:
1
var team = new Team();

dat gaat zonder problemen (zolang die imports erin zitten), maar Type.GetType("Team") werkt niet en geeft null 8)7
RTFM :P Type.GetType moet een fully qualified typename hebben tenzij het een mscorlib type is (bijvoorbeeld System.Int32).

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


  • NickThissen
  • Registratie: November 2007
  • Laatst online: 18-11 13:07
En Assembly.CreateQualifiedName("AcCtc", "AcCtc.Models.Team") is geen fully qualified typename? Zelfs "AcCtc.Models.Team" alleen zou al genoeg moeten zijn, vanmiddag nog getest en dat werkt (buiten t4 templates dan).

Die CreateQualifiedName geeft overigens "AcCtc.Models.Teams, AcCtc" terug, gewoon full name + assembly name dus. In t4 templates moet daar blijkbaar dus ook nog de version, culture en publickeytoken bij (ook al zijn die default / null).

Mijn iRacing profiel


  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Sebazzz schreef op woensdag 07 mei 2014 @ 21:57:
[...]

RTFM :P Type.GetType moet een fully qualified typename hebben tenzij het een mscorlib type is (bijvoorbeeld System.Int32).
Kleine toevoeging. Het hoeft alleen een assembly qualified name te hebbe als het type wat je zoekt niet in mscorlib of de huidig executerende assembly te vinden is. ;)
Pagina: 1