Ответ 1
Я реализовал что-то, что может помочь вам в самом последнем проекте, над которым я работаю. Мы используем AngularJS на интерфейсе и ASP.NET WEB API на внутреннем сервере. Все формы HTML генерируются автоматически на основе свойств и аннотаций данных, содержащихся в моих классах POCO.
На стороне сервера у меня есть сущности и DTO. Мои сущности содержат аннотации, специфичные для базы данных, и DTO содержат мои аннотации, специфичные для просмотра. Я приведу краткий пример, показывающий одно свойство в одном классе и как я создаю интерфейс для этого. Вот серверные объекты:
public class Discount
{
[StringLength(40)]
[Required]
public String Name { get; set; }
}
public class DiscountDto : IDto<Discount>
{
[Display(ResourceType = typeof(ApplicationStrings), Name = "Name", ShortName = "Name_Placeholder")]
[UI(Row = 1, Width = 6)]
public String Name { get; set; }
}
Это свойство отображается в пользовательском интерфейсе следующим образом:
<div class="form-group">
<label class="col-sm-2 control-label"> Name: </label>
<div class="col-sm-6">
<input class="form-control" ng-model="model[options.key]" required="required" maxlength="40" placeholder="Enter the name...">
</div>
</div>
Поле <input />
имеет автоматические настройки свойств required
, placeholder
и maxlength
. Метка HTML, ширина столбца начальной загрузки также автоматически настраиваются на основе пользовательской аннотации данных UI
. Строка = 1 означает отображение этого поля сначала в форме, а ширина = 6 означает, что поле должно занимать ширину столбца 6: class="col-sm-6"
. Текст ярлыка и текст заполнителя извлекаются из файлов ресурсов.
Если это то, что вы ищете, тогда прочитайте: -)
Я создал контроллер MetaController
, который принимает имя DTO как параметр: api/Meta/DiscountDTO
например. Этот контроллер просто выполняет все свойства объекта DTO и связанного с ним объекта и вытаскивает аннотации данных, преобразует их в класс FormMetadata
и возвращает List<FormMetadata>
клиенту. Класс FormMetadata
просто содержит такие свойства, как IsRequired
, IsDisplayed
, IsReadonly
и т.д., Чтобы превратить аннотации во что-то более читаемое для разработчиков интерфейсов. Вот фрагмент из MetaController:
var type = Type.GetType("<DTO_goes_here>");
List<FormMetadata> formMetadata = new List<FormMetadata>();
foreach (var prop in type.GetProperties())
{
var metadata = new FormMetadata();
metadata.Key = prop.Name.ToLower().Substring(0, 1) + prop.Name.Substring(1, prop.Name.Length - 1);
metadata.Type = prop.PropertyType.FullName;
object[] attrs = prop.GetCustomAttributes(true);
foreach (Attribute attr in attrs)
{
if (attr is RequiredAttribute)
{
metadata.IsRequired = true;
}
else if (attr is StringLengthAttribute)
{
var sla = (attr as StringLengthAttribute);
metadata.MinLength = sla.MinimumLength;
metadata.MaxLength = sla.MaximumLength;
}
// etc.
}
formMetadata.Add(metadata);
}
Эта конечная точка вернет следующий JSON для свойства Name:
{
"$id":"3",
"key":"name",
"display":"Name",
"type":"System.String",
"placeholder":"Enter the name...",
"isRequired":true,
"isEditable":true,
"isDisplayed":true,
"isReadonly":false,
"displayInList":true,
"width":6,
"row":1,
"col":0,
"order":0,
"maxLength":40,
"minLength":0,
"lookup":null,
"displayAs":null
}
На стороне клиента я создал настраиваемую директиву Angular <entity-form />
, которая принимает имя DTO как параметр:
<entity-form entity-type="DiscountDTO"></entity-form>
. Затем эта директива вызовет MetaController
, чтобы получить правила проверки для объекта Discount
и отобразить форму на основе возвращенных правил. Чтобы отобразить форму, я использую огромную библиотеку под названием angular-formly. Эта библиотека позволяет создавать формы из javascript без написания HTML. Я не буду подробно описывать здесь angular -formly, но вы в основном создаете объект Javascript с информацией о форме, которую хотите отобразить, и передаете ее в директиву angular -formly, и она заботится о предоставляя форму для вас. Это базовый пример типа объекта, который вы передаете angular -формативно, для рендеринга окна <input />
с меткой "Текст":
{
"key": "text",
"type": "input",
"templateOptions": {
"label": "Text",
"placeholder": "Type here to see the other field become enabled..."
}
}
Итак, я в основном беру метаданные, возвращенные из MetaController
, и создаю объект, который angular -форменно понимает и передает его в директиву angular -formly, и он отображает форму для меня. Я знаю, что этот ответ мог бы быть намного длиннее с большим количеством примеров и т.д., Но я чувствовал, что это было много, чтобы читать, как есть. Надеюсь, это даст вам достаточно информации.
Я хотел бы сделать это более общим и открытым исходным кодом - если кто-то заинтересован в том, чтобы работать над чем-то вроде этого, дайте мне знать: -)