Mar*_*tín 8 c# linq entity-framework odata asp.net-web-api
我正在使用C#中的WebApi项目(EF代码优先),我正在使用OData.我有一个"用户"模型,包含Id,Name,LastName,Email和Password.
在控制器例如我有这个代码:
// GET: odata/Users
[EnableQuery]
public IQueryable<User> GetUsers()
{
return db.Users;
}
Run Code Online (Sandbox Code Playgroud)
如果我调用/ odata/Users,我将获得所有数据:Id,Name,LastName,Email和Password.
如何从结果中排除密码,但在控制器中保持可用以进行Linq查询?
小智 15
我对这个话题有点迟,但我认为这可能对你有帮助.
我假设您需要加密密码以用于存储目的.你有没有看过使用odata动作来设置密码?使用操作可以在设置实体时忽略密码属性,同时仍向最终用户公开干净的方式来更新密码.
第一:忽略密码属性
builder.EntitySet<UserInfo>("UserInfo").EntityType.Ignore(ui => ui.Password);
Run Code Online (Sandbox Code Playgroud)
第二:添加你的odata动作
builder.EntityType<UserInfo>().Action("SetPassword").Returns<IHttpActionResult>();
Run Code Online (Sandbox Code Playgroud)
然后将SetPassword方法添加到UserInfoController.
它可能有点晚,但优雅的解决方案是添加自定义QueryableSelectAttribute,然后只列出要在服务端选择的字段.在你的情况下,它看起来像这样:
public class QueryableSelectAttribute : ActionFilterAttribute
{
private const string ODataSelectOption = "$select=";
private string selectValue;
public QueryableSelectAttribute(string select)
{
this.selectValue = select;
}
public override void OnActionExecuting(HttpActionContext actionContext)
{
base.OnActionExecuting(actionContext);
var request = actionContext.Request;
var query = request.RequestUri.Query.Substring(1);
var parts = query.Split('&').ToList();
for (int i = 0; i < parts.Count; i++)
{
string segment = parts[i];
if (segment.StartsWith(ODataSelectOption, StringComparison.Ordinal))
{
parts.Remove(segment);
break;
}
}
parts.Add(ODataSelectOption + this.selectValue);
var modifiedRequestUri = new UriBuilder(request.RequestUri);
modifiedRequestUri.Query = string.Join("&", parts.Where(p => p.Length > 0));
request.RequestUri = modifiedRequestUri.Uri;
base.OnActionExecuting(actionContext);
}
}
Run Code Online (Sandbox Code Playgroud)
在控制器中,您只需添加具有所需属性的属性:
[EnableQuery]
[QueryableSelect("Name,LastName,Email")]
public IQueryable<User> GetUsers()
{
return db.Users;
}
Run Code Online (Sandbox Code Playgroud)
就是这样!
当然,相同的原则可以应用于定制QueryableExpandAttribute.
小智 6
在User Class的Password属性中添加[NotMapped]属性,如下所示:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string LastName {get; set; }
[NotMapped]
public string Password {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
如何从结果中排除密码,但在控制器中保持可用以进行Linq查询?
忽略它.从ASP.NET Web API 2 OData的安全指南:
有两种方法可以从EDM中排除财产.您可以在模型类中的属性上设置[IgnoreDataMember]属性:
Run Code Online (Sandbox Code Playgroud)public class Employee { public string Name { get; set; } public string Title { get; set; } [IgnoreDataMember] public decimal Salary { get; set; } // Not visible in the EDM }您还可以通过编程方式从EDM中删除该属性:
Run Code Online (Sandbox Code Playgroud)var employees = modelBuilder.EntitySet<Employee>("Employees"); employees.EntityType.Ignore(emp => emp.Salary);
我为这个问题做了一个临时的解决方案(不是最好的解决方案,因为 UserInfo 不是实体类型并且不支持 $select 或 $expand)。我创建了一个名为 UserInfo 的新模型,其中包含我需要的属性(除了 User 之外):
public class UserInfo
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后我改变了控制器中的方法:
// GET: odata/Users
[EnableQuery]
public IQueryable<UserInfo> GetUsers()
{
List<UserInfo> lstUserInfo = new List<UserInfo>();
foreach(User usr in db.Users)
{
UserInfo userInfo = new UserInfo();
userInfo.Id = usr.Id;
userInfo.Name = usr.Name;
userInfo.Email = usr.Email;
lstUserInfo.Add(userInfo);
}
return lstUserInfo.AsQueryable();
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16777 次 |
| 最近记录: |