我正在尝试使用微风.js 保存一些实体。Breeze 工作正常,它会根据需要保存所有更改。但是,我无法验证和确保授权是服务器端。根据我目前收集到的信息,我想唯一的方法是检查传递到保存包中的 JObject 并在服务器端构造相应的对象。我必须这样做(而不是依赖 Breeze.SaveChanges,因为我在服务器端有一些逻辑)。我该怎么做呢?以及如何构建 Breeze.WebApi。保存结果?也非常欢迎任何其他解决此问题的方法的想法</p>
3 回答
这应该通过实现自定义来完成EFContextProvider
。
下面的代码实现了EFContextProvider
Northwind 数据库的自定义,直接取自Bread.com 网站上的文档。
公共类 NorthwindContextProvider: EFContextProvider<NorthwindIBContext> { 公共 NorthwindContextProvider() : base() { } protected override bool BeforeSaveEntity(EntityInfo entityInfo) { // 如果我们不想保存实体,则返回 false。 // 禁止添加任何类型为“角色”的实体 if (entityInfo.Entity.GetType() == typeof(Role) && entityInfo.EntityState == EntityState.Added) { 返回假; } 别的 { 返回真; } } 受保护的覆盖 Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap) { // 返回我们要保存的那些实体的地图。 返回保存地图; } }
@jaq316 是正确的:自定义EFContextProvider
是拦截来自客户端的更改的地方。它是授权和验证它们的地方。该文档有更多详细信息。它的本质是您在重写BeforeSaveEntity
和BeforeSaveEntities
虚拟方法中仔细检查建议的更改;或者,您可以将处理程序附加到BeforeSaveEntityDelegate
and BeforeSaveEntitiesDelegate
。
所以这是我对这个的想法,因为我根本没有使用 ContextProvider。我正在利用 SQL 后端和 Ninject 将存储库依赖项注入到我拥有的每个控制器中。我有比“Todos”演示更多的项目,并且还想要单独的控制器和存储库。如果我创建了如微风文档所示的 ContextProvider,我将拥有一个包含所有实体的 ContextProvider 文件。这将是巨大的。如果我将它们分成单独的上下文,我会在所有覆盖中复制代码。
这是我在 ContactFormController.cs 中保存更改的方法:
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
var sr = new SaveResult() { KeyMappings = new List<KeyMapping>(), Entities = new List<object>()};
dynamic entity = saveBundle["entities"][0];
ContactForm form = entity.ToObject<ContactForm>();
EntityState state = entity.entityAspect.entityState;
switch (state)
{
case EntityState.Added:
KeyMapping mapping = new KeyMapping(){EntityTypeName = typeof(ContactForm).ToString(), TempValue = form.Id };
var validationErrors = _contactFormService.ProcessContactForm(ref form).Cast<object>().ToList();
//if we succeed then update the mappings
if (validationErrors.Count == 0)
{
//setup the new mappings
mapping.RealValue = form.Id;
sr.KeyMappings.Add(mapping);
//link the entity
sr.Entities.Add(form);
}
else
{
sr.Errors = validationErrors;
}
break;
}
return sr;
}
我在客户端保存之前动态更改端点,以便我的 webapi 中的每个控制器都有一个 SaveChanges() 方法。然后我调用适当的存储库以根据需要处理后端功能。这样,我可以根据注入的 repo 运行模拟代码或实际的 SQL 更改。
如果它们是表单处理中的错误,那么我们将自定义 List 列表转换为 List 并将其分配给 SaveResult 的 Errors 属性。如果没有错误,我们会发回新的键映射以在客户端上更新。
理想情况下,我想减少此控制器中的所有代码,并可能将其抽象为实用方法,以便每个控制器中的重复更少。我喜欢这种方法,因为这样我就可以创建普通的存储库,而不是让它们依赖于 ContextProvider。那时微风独立。