在ASP .Net Core Web API

时间:2017-07-06 14:43:34

标签: c# asp.net-core-mvc state asp.net-core-webapi asp.net-core-1.1

我有一个ASP .Net Core 1.1 Web Api,它可以处理来自前端Web应用程序和手机应用程序的请求。该应用程序适用于房地产经纪人对物业进行检查。因此,该系统具有诸如检查,财产,用户,代理等的实体。用户(即房地产代理)和财产属于代理。因此,地产代理可以拥有一个或多个用户以及一个或多个房产。

例如,用户可能希望查看其地产代理商中任何人检查过的所有房产的清单。在这种情况下,他点击了网络/电话应用程序中的某个位置,应用程序向API发送HTTP GET请求以检索属性列表。 Web API在收到此请求后,首先检查哪个用户请求此请求,然后检查该用户所属的代理商,然后返回属于该代理商的所有属性。所以......这些是我所拥有的[简化]模型:

[Table("agency")]
public class Agency
{

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Column("agency_id")]
    public int? Id { get; set; }

    [Column("name")]
    public string Name { get; set; }
}

[Table("user")]
public class User
{

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Column("user_id")]
    public int? Id { get; set; }

    [Column("username")]
    public string Username { get; set; }

    [Column("agency_id")]
    public int AgencyId { get; set; }

    [ForeignKey("AgencyId")]
    public Agency Agency { get; set; }
}

[Table("property")]
public class Property
{

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Column("property_id")]
    public int? Id { get; set; }

    [Column("address")]
    public string Address { get; set; }

    [Column("agency_id")]
    public int AgencyId { get; set; }

    [ForeignKey("AgencyId")]
    public Agency Agency { get; set; }
}

处理上述请求的Web API上的控制器操作如下所示:

[Authorize]
[HttpGet]
public async Task<IActionResult> GetProperties()
{
    // Get Auth0 identifier for the user performing the request
    string nameIdentifier = User.Claims.FirstOrDefault(c => c.Type == System.Security.Claims.ClaimTypes.NameIdentifier)?.Value;
    // Retrieve this user from the database
    User user = await _context.User.SingleOrDefaultAsync(u => u.Username == nameIdentifier);
    // Return a list of properties that belong to the user's agency
    return Ok(_context.Properties
        .Where(p.AgencyId == user.AgencyId));
}

现在,所有对API的GET请求都会按此过滤 - 其中API返回与登录用户代理相关的记录。无论用户是否请求检查列表,房东或租户,API始终只返回属于用户代理的记录。

现在我知道ASP .Net Core是无状态的,因此我无法在用户登录时将用户对象保存在服务器上,并且可以在内存中准备好在每个控制器操作中调用它。但我觉得这次数据库往返每次API收到任何GET请求以找出该用户所属的代理商是浪费。有一个更好的方法吗?我对ASP和Web开发一般都很陌生。任何想法/提示/指针将不胜感激。

1 个答案:

答案 0 :(得分:5)

  

现在我知道ASP .Net Core是无状态的,因此我无法在用户登录时将用户对象保存在服务器上,并且可以在内存中准备好在每个控制器操作中调用它。但我觉得这次数据库的往返每次API收到任何GET请求,以找出该用户属于哪个代理商是浪费。


欢迎来到网络,这是一个无国籍的环境。如果您需要用户记录来处理每个http请求,您基本上有几个选择:

  1. 按要求从数据库中获取
  2. 将您需要的记录部分放入会话
  3. 将您需要的记录部分放入Cookie
  4. 每种方法都有利有弊。

    选项1将为您提供来自用户记录的绝对最新信息,但需要额外的数据库往返以满足任务要求。如果您有多个不同的记录需要处理请求,您可能会根据您的构建方式为每个请求进行多次数据库往返,

    如果您将Asp.Net Core应用程序配置为使用内存中会话提供程序,则选项2可以消除该数据库往返请求。但缺点是,如果Web应用程序被回收(如果在IIS后面运行则非常常见),那么会话将被清除。如果您将会话配置为使用像SqlServer这样的数据库提供程序,那么当它从数据库中读取会话时,您仍然会为每个请求执行数据库往返(但这只是一次往返而不是几次,具体取决于您拥有的内容放置在会话中以及编译信息需要多少次数据包往返。)在数据库支持的会话中放置信息的一个缺点是它会强制数据库往返每个请求,即使请求不需要任何信息被安排在会议中。如果你不小心会话中存储的数据大小(并从数据库中查询每个请求)会很快变得非常大。它有时候太容易“只是把它扔进会话”,这最终会导致性能问题。

    选项3将所需数据放入cookie中,该cookie将与http请求标头中的每个请求一起传送。这样做的缺点是它会使每个文件请求略微增大(通常甚至是图像请求),并且您可能希望将cookie限制为仅https请求以防止信息通过互联网以明文形式传输。这种方法通常仅用于非常少量的数据。

    此摘要绝不是详尽无遗的,还有其他方法可以跟踪状态(查询参数等)以及所选方法的其他安全注意事项。主要的一点是,是的,网络是一个无国籍的环境,但仍然有办法跟踪状态,但是所有这些都有利有弊,没有一种方法总是最好的。大多数大型Web应用程序使用所有可用方法的变体来处理其Web应用程序的不同方面。

    您可以在此处阅读有关Asp.Net Core会话和应用程序状态的更多信息:https://docs.microsoft.com/en-us/aspnet/core/fundamentals/app-state