You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Get方法中获取Post提交的基金名称以切换数据库连接

问题描述

数据库连接需根据用户所属基金确定:

  • 普通用户通过Claims中的caisse值获取对应ConnectionString
  • 管理员可选择目标基金,通过Post提交基金名称到API,需要在Get方法中获取该名称,匹配对应ConnectionString执行SQL查询
    当前无法实现Post到Get方法间的参数传递。

现有配置(appsettings.json)

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=.\\SQLEXPRESS; Database=Ctisn; Trusted_Connection=True; MultipleActiveResultSets=True;",
    "MECLESINE": "Server=myserver; Database=aicha_meclesine; User ID=***; Password=***;",
    "FONEES": "Server=myserver; Database=aicha_fonees; User ID=***; Password=***;",
    "MECFP": "Server=myserver; Database=aaicha_mecfp; User ID=***; Password=***;",
    "MECCT": "Server=myserver; Database=aicha_ct; User ID=***; Password=***;",
    "JSR": "Server=myserver; Database=aicha_jsr; User ID=***; Password=***;"
  }
}

现有控制器代码

[Authorize]
[Route("api/[controller]")]
[ApiController]
public class TopClientsController : ControllerBase
{
    private readonly IConfiguration _configuration;

    public TopClientsController(IConfiguration configuration)
    {
        _configuration = configuration;
    }
    
    [HttpPost("{AdminValue}")]
    public JsonResult Post(string AdminValue)
    {
        return new JsonResult(new { data = AdminValue });
    }

    [HttpGet]
    public JsonResult Get()
    {
        string query = @"
        -------------------My sql requet-----------------
        ";
        var iden;

        if (User.IsInRole("Administrator"))
        {
            // iden = The result of the post methode  ;
        }
        else
        {
            iden=((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirst("caisse").Value;
        }


        DataTable table = new DataTable();
        string sqlDataSource = _configuration.GetConnectionString($"{iden}");
        MySqlDataReader myReader;
        using (MySqlConnection mycon = new MySqlConnection(sqlDataSource))
        {
            mycon.Open();
            using (MySqlCommand myCommand = new MySqlCommand(query, mycon))
            {
                myReader = myCommand.ExecuteReader();
                table.Load(myReader);

                myReader.Close();
                mycon.Close();
            }
        }

        return new JsonResult(table);
    }
}
解决方案

API本身是无状态的,Post和Get是两个独立请求,无法直接传递内存中的值。以下是几种可行的实现方式:

方式1:修改Get接口,通过查询参数传递基金名称

直接调整Get方法,允许管理员传入基金名称作为查询参数,普通用户仍使用Claims值,这是最符合RESTful设计的方案:

[HttpGet]
public JsonResult Get([FromQuery] string? fundName = null)
{
    string query = @"
    -------------------My sql requet-----------------
    ";
    string iden;

    if (User.IsInRole("Administrator"))
    {
        // 管理员需指定基金名称,同时校验合法性
        if (string.IsNullOrEmpty(fundName))
        {
            return new JsonResult("管理员需指定基金名称") { StatusCode = 400 };
        }
        if (!_configuration.GetSection("ConnectionStrings").GetChildren().Any(c => c.Key == fundName))
        {
            return new JsonResult("无效的基金名称") { StatusCode = 400 };
        }
        iden = fundName;
    }
    else
    {
        iden = ((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirst("caisse").Value;
    }

    // 后续数据库操作逻辑保持不变
    DataTable table = new DataTable();
    string sqlDataSource = _configuration.GetConnectionString($"{iden}");
    MySqlDataReader myReader;
    using (MySqlConnection mycon = new MySqlConnection(sqlDataSource))
    {
        mycon.Open();
        using (MySqlCommand myCommand = new MySqlCommand(query, mycon))
        {
            myReader = myCommand.ExecuteReader();
            table.Load(myReader);

            myReader.Close();
            mycon.Close();
        }
    }

    return new JsonResult(table);
}

管理员直接通过GET /api/TopClients?fundName=MECLESINE请求数据即可,原Post方法可删除。

方式2:使用Cookie存储管理员选择的基金名称

若必须保留Post提交逻辑,可在Post方法中将基金名称写入Cookie,Get方法读取该Cookie:

[HttpPost("{AdminValue}")]
public JsonResult Post(string AdminValue)
{
    // 先校验基金名称合法性
    if (!_configuration.GetSection("ConnectionStrings").GetChildren().Any(c => c.Key == AdminValue))
    {
        return new JsonResult("无效的基金名称") { StatusCode = 400 };
    }
    // 设置Cookie,配置安全属性
    Response.Cookies.Append("SelectedFund", AdminValue, new CookieOptions
    {
        HttpOnly = true,
        Secure = true,
        SameSite = SameSiteMode.Strict,
        Expires = DateTimeOffset.UtcNow.AddHours(1)
    });
    return new JsonResult(new { data = AdminValue });
}

[HttpGet]
public JsonResult Get()
{
    string query = @"
    -------------------My sql requet-----------------
    ";
    string iden;

    if (User.IsInRole("Administrator"))
    {
        // 从Cookie读取基金名称
        if (!Request.Cookies.TryGetValue("SelectedFund", out string? fundName) || string.IsNullOrEmpty(fundName))
        {
            return new JsonResult("管理员需先选择基金") { StatusCode = 400 };
        }
        iden = fundName;
    }
    else
    {
        iden = ((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirst("caisse").Value;
    }

    // 后续数据库操作逻辑保持不变
    DataTable table = new DataTable();
    string sqlDataSource = _configuration.GetConnectionString($"{iden}");
    MySqlDataReader myReader;
    using (MySqlConnection mycon = new MySqlConnection(sqlDataSource))
    {
        mycon.Open();
        using (MySqlCommand myCommand = new MySqlCommand(query, mycon))
        {
            myReader = myCommand.ExecuteReader();
            table.Load(myReader);

            myReader.Close();
            mycon.Close();
        }
    }

    return new JsonResult(table);
}

Cookie与用户会话绑定,单用户场景下不会互相干扰,适合单机部署的系统。

方式3:使用分布式缓存存储管理员选择的基金

若系统为多服务器部署,Cookie无法跨节点共享,可使用Redis等分布式缓存:
首先注入IDistributedCache:

private readonly IConfiguration _configuration;
private readonly IDistributedCache _distributedCache;

public TopClientsController(IConfiguration configuration, IDistributedCache distributedCache)
{
    _configuration = configuration;
    _distributedCache = distributedCache;
}

然后修改Post和Get方法:

[HttpPost("{AdminValue}")]
public async Task<JsonResult> Post(string AdminValue)
{
    if (!_configuration.GetSection("ConnectionStrings").GetChildren().Any(c => c.Key == AdminValue))
    {
        return new JsonResult("无效的基金名称") { StatusCode = 400 };
    }
    // 用用户ID作为缓存键,确保每个管理员的选择独立
    string userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? throw new UnauthorizedAccessException();
    await _distributedCache.SetStringAsync($"AdminSelectedFund:{userId}", AdminValue, new DistributedCacheEntryOptions
    {
        AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1)
    });
    return new JsonResult(new { data = AdminValue });
}

[HttpGet]
public async Task<JsonResult> Get()
{
    string query = @"
    -------------------My sql requet-----------------
    ";
    string iden;

    if (User.IsInRole("Administrator"))
    {
        string userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? throw new UnauthorizedAccessException();
        string? fundName = await _distributedCache.GetStringAsync($"AdminSelectedFund:{userId}");
        if (string.IsNullOrEmpty(fundName))
        {
            return new JsonResult("管理员需先选择基金") { StatusCode = 400 };
        }
        iden = fundName;
    }
    else
    {
        iden = ((System.Security.Claims.ClaimsIdentity)User.Identity).FindFirst("caisse").Value;
    }

    // 后续数据库操作逻辑保持不变
    DataTable table = new DataTable();
    string sqlDataSource = _configuration.GetConnectionString($"{iden}");
    MySqlDataReader myReader;
    using (MySqlConnection mycon = new MySqlConnection(sqlDataSource))
    {
        mycon.Open();
        using (MySqlCommand myCommand = new MySqlCommand(query, mycon))
        {
            myReader = myCommand.ExecuteReader();
            table.Load(myReader);

            myReader.Close();
            mycon.Close();
        }
    }

    return new JsonResult(table);
}

这种方式适合分布式部署的系统,但需要提前配置好分布式缓存服务。

内容的提问来源于stack exchange,提问作者Mouhamed Diop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 14:05:23