目标
我的目标是在实体产品中发送一些额外的(未定义的)属性。例如,在AngularJs列表视图中,我需要根据从会话获取的当前用户数据和productId计算的权限来显示某些产品作为链接(可访问),而其他产品则不能访问。
导致我出现这个问题的原因
现在,Odata不允许我在发送IQueryable结果时添加额外的属性,如下所示。
public IQueryable<Product> GET()
{
return db.Products.AsQueryable<Product>();
}
仅仅因为返回类型是Product,添加额外的属性将会把它变成别的东西,如果我像这样尝试:
var result = db.Products.Select(p => new Product
{
ID = p.ID,
Accessible = (code for permission checks),
[other properties...]
}
解决方案
我采用了一种解决方案,创建了一个新类型的OdataController,即OdataProduct,它具有我需要发送的已定义属性,以使列表权限生效。(您有没有其他方法使列表权限生效,除了我提出的这种解决方案?)
public class OdataProduct
{
public Product product { get; set; }
public OdataProduct(Product product)
{
this.product = product;
}
//
public void setPermissions(User user, string controller)
{
if (user == null) return;
isAllowed = [permission check code];
}
public bool isAllowed { get; set; }
}
我试图从Product
继承OdataProduct
,但在接收POST
请求以保存到数据库时,将OdataProduct
向下转型为Product
时遇到了问题。Db.Products.Add();
现在,有了这个ViewModel
和这种类型的控制器,我已成功发送了基于当前用户会话的权限感知结果,用于列表中所有产品。
public class OdataProductController : ODataController
{
private OfferAssistantDbContext db = new OfferAssistantDbContext();
// GET api/OdataProduct
public IQueryable<OdataProduct> GET()
{
var result = db.Products.AsQueryable<Product>();
var OResult = new List<OdataProduct>();
var currentUser = (User)HttpContext.Current.Session["LoggedUser"];
OdataProduct OProduct;
foreach (var item in result)
{
OProduct = new OdataProduct(item);
OProduct.setPermissions(currentUser, "Product");
OResult.Add(OProduct);
}
return OResult.AsQueryable<OdataProduct>();
}
//other methods of the controller below...
}
我想要解决的问题
当我向
OdataProduct
控制器发送PATCH
请求时,我得到一个Delta对象,而不是Product。如果我在Payload
中发送一个Product,并相应地修改PATCH
方法的Odata参数以接收一个Product而不是OdataProduct,那么它将被接收为null,而在默认情况下,我无法运行这个命令对真正的Product实体进行而不是ViewModel
。以下是:var dbProduct = db.Products.Find(key); oDataProduct.Patch((dbProduct); //OdataProduct is not of dbProduct type 有什么解决办法吗?
我面临的另一个问题是设置上面的OdataProduct的权限。
OProduct.setPermissions(currentUser, "Product"); //进入这个方法后,异常行是 this.Childs = product.DependantProducts.Where(dp => dp.ParentID == product.ID).Count();
它说DataReader已经打开。虽然这不是主要问题,但请在此处提供一些信息。
builder.EntitySet<Product>("Product").EntityType.Property(c => c.IsAccessible);
还需要初始化它以使其与LINQ to Queryable一起使用,如下所示var result = db.Products.ToList().Where(p => p.IsAccessible == p.IsAccessible);
在您的控制器->GET中。 - ahmadalibaloch