Reputation: 51
I am trying to get asp.net core MVC to scaffold a Razor View with fields in a different order than the apparently default alphabetical order. I've got a simple model:
public class Application : EntityBase
{
[Display(Name = "Naam", Order = 1)]
public string Name { get; set; }
[Display(Name = "Omschrijving", Order = 2)]
public string Description { get; set; }
}
I want the scaffolder to generate a field for Name before Description. How to do this?
I've been trying to come up with a solution in the Razor template. The relevant code is:
...
IEnumerable<PropertyMetadata> properties = Model.ModelMetadata.Properties;
foreach (var property in properties)
{
if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
{
...
I was hoping that a property had an Order-property, so I could write something like
foreach (var property in properties.OrderBy(p => p.Order))
Any ideas?
Upvotes: 3
Views: 312
Reputation: 51
So, after some (deep) digging I came up with a solution. As I allready customized the templates, it was acceptable to add yet another customization. I ended up creating a helper class ScaffoldHelpers.cs:
public class ScaffoldHelpers
{
public static IEnumerable<PropertyMetadata> GetPropertiesInDisplayOrder(string typename, IEnumerable<PropertyMetadata> properties)
{
Type type = Type.GetType($"{typename}, {typename.Split('.')[0]}");
SortedList<string, PropertyMetadata> propertiesList = new SortedList<string, PropertyMetadata>();
foreach (PropertyMetadata property in properties)
{
int order = 0;
if (type != null)
{
var member = type.GetMember(property.PropertyName)[0];
var displayAttribute = member.GetCustomAttribute<System.ComponentModel.DataAnnotations.DisplayAttribute>();
if (displayAttribute != null)
{
order = displayAttribute.Order;
}
}
propertiesList.Add($"{order:000} - {property.PropertyName}", property);
}
return propertiesList.Values.AsEnumerable();
}
}
This iterates over all the properties, and determines if a [Display()] attribute is specified. If so, it gets the value of the Order-parameter. If you don't specify this, the Order-property will be zero. Using a SortedList and making sure the key is ordered by the specified order, I'm able to easily return an IEnumerable<PropertyMetadata>
in the desired order.
In the template, I needed to add @using
for this helper-class. After that, I could insert the following into the template:
...
IEnumerable<PropertyMetadata> properties = Model.ModelMetadata.Properties;
// added:
properties = ScaffoldHelpers.GetPropertiesInDisplayOrder(Model.ViewDataTypeName, properties);
foreach (var property in properties)
{
if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey)
{
...
That's it!
Upvotes: 2