我正在尝试使用breeze.js保存一些实体。 Breeze工作正常,它会根据需要保存所有更改。但是,我无法验证并确保授权是服务器端。从我到目前为止收集的内容来看,我想要做到这一点的唯一方法是检查传递给保存包的JObject并在服务器端构建相应的对象。我必须这样做(而不是依赖Breeze.SaveChanges,因为我在服务器端有一些逻辑)。我该怎么做呢?我如何构建Breeze.WebApi。 SaveResult? 任何其他解决这个问题的方法的想法也非常受欢迎
答案 0 :(得分:2)
这应该通过实施自定义EFContextProvider
来完成。
下面的代码为Northwind数据库实现了自定义EFContextProvider
,并直接从documentation on the breeze.com website获取。
public class NorthwindContextProvider: EFContextProvider<NorthwindIBContext> { public NorthwindContextProvider() : base() { } protected override bool BeforeSaveEntity(EntityInfo entityInfo) { // return false if we don’t want the entity saved. // prohibit any additions of entities of type 'Role' if (entityInfo.Entity.GetType() == typeof(Role) && entityInfo.EntityState == EntityState.Added) { return false; } else { return true; } } protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap) { // return a map of those entities we want saved. return saveMap; } }
答案 1 :(得分:2)
@ jaq316是正确的:a custom EFContextProvider
是拦截来自客户端的更改的地方。它是授权和验证它们的地方。 documentation has more details。{{3}}。它的本质是您在BeforeSaveEntity
和BeforeSaveEntities
虚拟方法的覆盖范围内仔细检查建议的更改;或者,您可以将处理程序附加到BeforeSaveEntityDelegate
和BeforeSaveEntitiesDelegate
。
答案 2 :(得分:1)
所以这是我对这个的想法,因为我根本没有使用ContextProvider。我正在利用SQL后端和Ninject将存储库依赖注入到我拥有的每个控制器中。我有比“Todos”的演示更多的项目,并且还需要单独的控制器和存储库。如果我创建了像breeze docs所示的ContextProvider,我将有一个ContextProvider文件,其中包含所有实体。这将是巨大的。如果我将它们分成不同的上下文,我会在所有覆盖中复制代码。
这是ContactFormController.cs中的Save Changes方法:
[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并将其分配给SaveResult的Errors属性。如果没有错误,我们会发回新的密钥映射以在客户端上更新。
理想情况下,我希望减少此控制器中的所有代码,并可能将其抽象为实用程序方法,以便每个控制器中的重复次数更少。我喜欢这种方法,因为那时我可以创建普通的存储库,而不是让它们依赖于ContextProvider。微风独立于那一点。