我正在使用DataAnnotations编写MVC2应用程序.我有以下型号:
public class FooModel
{
[ScaffoldColumn("false")]
public long FooId { get; set; }
[UIHint("BarTemplate")]
public DateTime? Bar { get; set;}
}
Run Code Online (Sandbox Code Playgroud)
我想为Bar创建一个自定义显示模板.我创建了以下模板:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DateTime?>" %>
<div class="display-label">
<span><%: Html.LabelForModel() %></span>
</div>
<div class="display-field">
<span><%: Html.DisplayForModel()%></span>
<%: Html.ActionLink("Some link", "Action", new { id = ??FooId?? }) %>
</div>
Run Code Online (Sandbox Code Playgroud)
现在,我的问题是Bar的内部模板我想从我的模型访问另一个属性.我不想为FooModel创建单独的模板,因为我将不得不对所有其他FooModel属性进行硬编码.
在使用调试器进行简短调查后,我可以看到:
this.ViewData.ModelMetadata.ContainerType
是FooModel(正如预期的那样)this.ViewData.TemplateInfo有一个非公共属性VisitedObjects
(类型
System.Collections.Generic.HashSet<object>),包含两个元素:
FooModel和DateTime?.如何访问我的FooModel?我不想破解我使用Reflection的方法.
更新:
我已经接受了mootinator的回答,因为它认为我是允许类型安全的最佳解决方案.我也赞成了Tx3的答案,因为mootinator的答案建立在它之上.尽管如此,我认为在这种场景中应该有更好的MVC支持,我认为这在现实世界中非常普遍,但在示例应用程序中却缺少.
ASP.NET MVC 2中的继承属性和MetadataType似乎不适用于客户端验证.
我们的MetadataTypes验证在服务器上按预期工作,但由于某种原因,它不会为它生成适当的客户端脚本.对于在PersonView上设置了DataAnnotations属性的属性,客户端验证会按预期启动,因此我知道客户端验证是活动的并且它可以正常工作.有谁知道它是否或如何修复?
这是我们拥有的:
public abstract class PersonView
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
[Required] public string PhoneNumber { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressZipCode { get; set; }
public string AddressCity { get; set; }
public string AddressCountry { get; set; }
}
[MetadataType(typeof(CustomerViewMetaData))]
public class CustomerView …Run Code Online (Sandbox Code Playgroud) 我有一个viewmodel,它包含一个TestThing类型的复杂属性,声明为:
public class TestThing
{
[Display(Name = "String3", Prompt = "String4")]
public string Test1 { get; set; }
[Display(Name = "String5", Prompt = "String6")]
public string Test2 { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我有一个这种类型的EditorTemplate,我希望能够访问每个子属性的元数据.例如,如果模板用于字符串,我可以通过使用来访问提示文本@ViewData.ModelMetadata.Watermark,但因为它是复杂类型,所以我不能使用此方法.
还有其他选择吗?
asp.net-mvc editortemplates modelmetadata razor asp.net-mvc-3
我需要澄清如何实现Betty的代码解决方案,以便使用AutoMapper将数据注释元数据传输到ViewModels(参见此处).或者,如果你有更好的方法,请分享.也许对于熟悉AutoMapper的人来说,实现贝蒂的答案是显而易见的,但我是新手.
这是一个简单的例子,我将如何添加到此代码中以使Betty的解决方案工作:
// Data model Entity
public class User1
{
[Required]
public int Id { get; set; }
[Required]
[StringLength(60)]
public string FirstName { get; set; }
[Required]
[StringLength(60)]
public string LastName { get; set; }
[Required]
[DataType(DataType.Password)]
[StringLength(40)]
public string Password { get; set; }
}
// ViewModel
public class UserViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
当前的AutoMapper实现:
// Called …Run Code Online (Sandbox Code Playgroud) 我已经开发了一个MVC帮助器来生成显示和可编辑表(需要一个jquery插件来允许在可编辑表中动态添加和删除具有完全回发的行),例如
@Htm.TableDisplayFor(m => m.MyCollection as ICollection)
Run Code Online (Sandbox Code Playgroud)
与属性一起使用的将包括页脚中的总计,添加用于查看和编辑链接的列,为复杂类型呈现超链接等.例如
[TableColumn(IncludeTotals = true)]
Run Code Online (Sandbox Code Playgroud)
我即将在CodeProject上发布它,但在此之前,我想解决一个问题.帮助程序首先ModelMetadata从表达式中获取,检查它是否实现ICollection,然后获取集合中的类型(注意以下代码片段来自SO上的已接受答案,但如下所述,并不完全正确)
if (collection.GetType().IsGenericType)
{
Type type = collection.GetType().GetGenericArguments()[0]
Run Code Online (Sandbox Code Playgroud)
该类型用于生成ModelMetadata表头(表中可能没有任何行)和表体中的每一行(如果某些项是继承类型,具有其他属性,否则会搞乱列布局)
foreach (var item in collection)
{
ModelMetadata itemMetadata = ModelMetadataProviders.Current
.GetMetadataForType(() => item, type);
Run Code Online (Sandbox Code Playgroud)
我希望能够做的是使用IEnumerable,而不是ICollection让.ToList()不需要它的LINQ表达式被调用.
在大多数情况下,IEnumerable工作正常
IEnumerable items = MyCollection.Where(i => i....);
Run Code Online (Sandbox Code Playgroud)
没问题因为.GetGenericArguments()返回一个只包含一种类型的数组.问题是某些查询的'.GetGenericArguments()'返回2种或更多类型,似乎没有逻辑顺序.例如
IEnumerable items = MyCollection.OrderBy(i => i...);
Run Code Online (Sandbox Code Playgroud)
返回[0]集合中的类型,[1]用于排序的类型.
在这种情况下.GetGenericArguments()[0]仍然有效,但是
MyCollection.Select(i => new AnotherItem()
{
ID = i.ID,
Name = 1.Name
} …Run Code Online (Sandbox Code Playgroud) 我有一个 ASP.NET Core 3.1 Web API 应用程序,它的端点使用了各种模型来输入和输出数据。因为其他 C# 应用程序将与这个应用程序通信,所以我决定将这些共享模型移动到所有应用程序都可以使用的 NuGet 包中。
像往常一样,这些模型的属性用各种数据注释属性装饰,例如[Required],以允许标准模型验证以防止无效输入。它们还使用特定的 ASP.NET MVC Core 属性(例如 )进行修饰,[FromQuery]以允许它们正确绑定到传入请求。
但是,我不希望 ASP.NET MVC Core 属性出现在共享 NuGet 包中。首先,因为它们只与 Web API 相关,所以在那里应用它们是有意义的;其次,因为将它们包含在 NuGet 中将引入各种与 ASP.NET Core 相关的依赖项,这些依赖项再次与此包的其他使用者无关。
ASP.NET Core 具有[ModelMetadataType]涵盖这一点的属性 - 但仅当有问题的模型驻留在同一程序集中时。是否有一种内置或简单的方法可以[ModelMetadataType]跨不同的程序集工作,而无需子类化和/或重新声明模型?
(我完全清楚,允许下游消费者潜在地改变上游模型的行为,因此允许这样做会产生安全风险,但由于这些模型和这个包以及有问题的应用程序都是我工作的公司内部的,所以在这种情况下不是问题。)
说明基本概念的代码示例:
// NuGet package - model declaration
public class MyModel
{
[Required]
public int MyProperty { get; set; }
}
...
// ASP.NET Core web API - enrich model with additional metadata
public …Run Code Online (Sandbox Code Playgroud) c# modelmetadata asp.net-core asp.net-core-webapi asp.net-core-3.1
在我的ASP.NET MVC应用程序中,我在数据库中定义了基于元数据的模型.我有一个定义数据元数据的自定义对象,并使用DTO数据集.为了显示这一点,我打算编写一个自定义的ModelMetadataProvider和ModelValidatorProvider.
这是正确的方法吗?
关于自定义ModelMetadataProvider和ModelValidatorProvider的任何指针?
我有一个ASP.NET MVC 4站点,我将一个嵌套属性传递给EditorTemplate并使用构建字段名称,ViewData.ModelMetadata.PropertyName但是,它获取子属性的属性名称,而不是属性的完整点符号名称我是编辑.
一个例子将说明最佳:
鉴于以下类型
public class EditEntityViewModel
{
// elided
public Entity Entity { get; set}
}
public class Entity
{
// elided
public string ImageUrl { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我的编辑和创建视图如下:
@model EditEntityViewModel
<div>
@Html.EditorFor(model => model.Entity.ImageUrl , "_ImageUploader")
</div>
Run Code Online (Sandbox Code Playgroud)
_ImageUploader.cshtml编辑器模板如下
@model System.String
<div class="uploader">
@Html.LabelFor(model => model)
@Html.HiddenFor(model => model)
<div data-rel="@(ViewData.ModelMetadata.PropertyName)">
<input type="file" name="@(ViewData.ModelMetadata.PropertyName)Upload" />
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
渲染的HTML看起来像这样
<div>
<div class="uploader">
<label for="Entity_ImageUrl">Image</label>
<input id="Entity_ImageUrl" name="Entity.ImageUrl" type="hidden"/>
<div data-rel="ImageUrl"> <!-- Problem -->
<input type="file" …Run Code Online (Sandbox Code Playgroud) 我正在看到其他方法,例如AdditionalValues,但我想知道是否有可能最终在一个场景中你可以向模板视图中可用的ModelMetadata对象添加新属性.
例如,您可以:
@ViewData.ModelMetadata.MvvmBound
Run Code Online (Sandbox Code Playgroud)
我想在编辑器和显示模板中使用它来将MVVM属性添加到正在呈现的HTML元素中.
我完全迷失了,但到目前为止,这是我的努力:
public class MyModelMetaDataProvider : DataAnnotationsModelMetadataProvider
{
protected new MyModelMetaData CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
{
ModelMetadata modelMetaData = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
MyModelMetaData myMetaData = (MyModelMetaData)modelMetaData;
return myMetaData;
}
}
public class MyModelMetaData: ModelMetadata
{
public MyModelMetaData(ModelMetadataProvider provider, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
: base(provider, containerType, modelAccessor, modelType, propertyName)
{
}
public int MyProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后在全球的asax我使用:
ModelMetadataProviders.Current =new MyModelMetaDataProvider();
Run Code Online (Sandbox Code Playgroud)
问题是如果我尝试在视图中使用MyProperty它无法识别,我预期,因为VS不知道自定义ModelMetadata类.
我甚至不确定这是可能的吗?
asp.net-mvc modelmetadata modelmetadataprovider asp.net-mvc-4
我试图弄清楚如何使用MVC3 RC2和使用DataAnnotations修饰的模型格式化日期.
这是我的模特......
public class Model
{
[Display(Name = "Date of Birth")]
[DisplayFormat(@DataFormatString = "MM/dd/yyyy")]
public DateTime DateOfBirth { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是我的控制器......
public class IndexController : Controller
{
public ActionResult Index()
{
return View( new Model() {DateOfBirth = DateTime.Now});
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的看法......
@model MvcApplication6.Models.Model
@Html.LabelFor(m=>m.DateOfBirth)
@Html.TextBoxFor(m => m.DateOfBirth)
@Html.EditorFor(m => m.DateOfBirth)
Run Code Online (Sandbox Code Playgroud)
当我运行该站点时,对于两个控件,页面显示一个文本框,其中包含时间字符串,当我想要的只是日期(由模型中的装饰属性指定).
我在这个模式中使用了Brad Wilson 关于ModelMetaData 的文章.
我做错了很明显吗?
asp.net-mvc datetime modelmetadata data-annotations asp.net-mvc-3
在Entity Framework 6中,我可以像这样获得类(myModel)的ModelMetadata:
var modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, myModel.GetType());
Run Code Online (Sandbox Code Playgroud)
在.net core 1.1.1中我该怎么做?
我刚读完http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html文章Brad列出了该Watermark属性,但没有提及哪个DataAnnotation用于填充它.
出于某种原因,当我试图反思这个类时,.NET Reflector会引发异常.它适用于其他一切.
请问是什么源代码DataAnnotationsModelMetadataProvider?
modelmetadata data-annotations modelmetadataprovider asp.net-mvc-3 asp.net-mvc-2
modelmetadata ×13
asp.net-mvc ×6
asp.net ×2
asp.net-core ×2
c# ×2
automapper ×1
datetime ×1
linq ×1
model ×1
razor ×1
templates ×1
validation ×1