无论调用了什么API路由,如何始终执行功能?

时间:2018-10-02 17:00:33

标签: asp.net-core-2.0 asp.net-core-webapi

我正在创建NetCore 2 API并连接到SQL Server数据库。无论路由是什么,都可以始终调用函数吗?我的例子:

对于每个调用,我都传递必要的参数以连接到标题中的SQL DB。我将在此api中进行数百次调用,因此我真的不想为每个调用重复此操作:

    [HttpGet]
    public async Task<IEnumerable<DEPARTMENT>> Get(
        [FromHeader] string Server, 
        [FromHeader] string Database, 
        [FromHeader] string Username, 
        [FromHeader] string Password, 
        [FromHeader] string Trusted)
    {
        util.SetConnectionString(Server, Database, Username, Password, Trusted);
        return await this.departmentDataProvider.GetDepartments();
    }

    [HttpGet("{DepartmentId}")]
    public async Task<IEnumerable<DEPARTMENT>> Get(
        string DepartmentId,
        [FromHeader] string Server, 
        [FromHeader] string Database, 
        [FromHeader] string Username, 
        [FromHeader] string Password, 
        [FromHeader] string Trusted)
    {
        util.SetConnectionString(Server, Database, Username, Password, Trusted);
        return await this.departmentDataProvider.GetDepartment(DepartmentId);
    }

我想创建一个仅具有标头连接参数和设置连接字符串的调用的祖先函数。最终目标将是这样的:

祖先:

    [HttpGet]
    public async Task<IEnumerable<?>> Get(
        [FromHeader] string Server,
        [FromHeader] string Database,
        [FromHeader] string Username,
        [FromHeader] string Password,
        [FromHeader] string Trusted)
    {
        util.SetConnectionString(Server, Database, Username, Password, Trusted);
    }

孩子:

    [HttpGet]
    public async Task<IEnumerable<DEPARTMENT>> Get()
    {
        return await this.departmentDataProvider.GetDepartments();
    }

    [HttpGet("{DepartmentId}")]
    public async Task<IEnumerable<DEPARTMENT>> Get(string DepartmentId)
    {
        return await this.departmentDataProvider.GetDepartment(DepartmentId);
    }

编辑:

添加Util.cs和DepartmentDataProvider.cs以获取更多信息。

Util.cs

public static class util
{
    public static string ConnectionString { get; set; }

    public static void SetConnectionString(string Server, string Database, string UserName, string Password, string Trusted)
    {
        if (Trusted == "true")             
            ConnectionString = "Server=" + Server + ";Database=" + Database + ";Trusted_Connection=True;";
        else
            ConnectionString = "Server=" + Server + ";Database=" + Database + ";User ID= " + UserName + ";Password=" + Password + ";Trusted_Connection=False;";
    }

    public static string GetConnectionString()
    {
        return ConnectionString;
    }
}

DepartmentDataProvider.cs

public class DepartmentDataProvider : IDepartmentDataProvider
{
    public async Task<DEPARTMENT> GetDepartment(int DepartmentId)
    {
        string connString = util.GetConnectionString();

        using (var sqlConnection = new SqlConnection(util.GetConnectionString()))
        {
            await sqlConnection.OpenAsync();
            var dynamicParameters = new DynamicParameters();
            dynamicParameters.Add("@DepartmentID", DepartmentId);
            return await sqlConnection.QuerySingleOrDefaultAsync<DEPARTMENT>(
                "Select * From DEPARTMENT Where DEPARTMENT_ID = @DepartmentID",
                dynamicParameters,
                commandType: CommandType.Text);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

创建一个类来封装将要注入任何相关对象的连接字符串数据(例如,HttpContext):

public class ConnectingStringParmsFromHeaders
{
    public string Server { get; private set; }
    // other properties

    // ideally you wouldn't depend on ASP.NET Core constructs such as HttContext
    //   but I'm using it here for brevity
    public ConnectionStringPropertiesFromHeaders( HttpContext httpContext )
    {
        ReadPropertiesFromHeaders( httpContext.Request.Headers );
    }

    private void ReadPropertiesFromHeaders( IHeaderDictionary headers )
    {
        // do your header-reading thing here
    }

    public string BuildConnectionString()
    {
        // your Util.SetConnectionString(...) code here
        //   using local instance properties and not static properties
    }
}

接下来,register个此类的生存期为Scoped(在同一HTTP请求中重用单个对象):

public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddScoped<ConnectionStringParmsFromHeaders>();
}

最后,将这种类型的参数添加到控制器的构造函数中,并设置要在操作方法中使用的属性或字段:

public class DepartmentsController : Controller
{
    private ConnectionStringParmsFromHeaders ConnStrParms { get; private set; }

    public DepartmentsController( ConnectionStringParmsFromHeaders connStrParms )
    {
        ConnStrParms = connStrParms;
    }

    public async Task<IActionResult> Get()
    {
        // for illustrative purposes
        var connStr = connStrParms.BuildConnectionString();

        // remainder of your action method's code
    }
}

请注意,您的Util类使用每HTTP请求标头数据设置静态属性是一个问题b / c可能会有多个并发线程同时读取和写入相同的属性和不同的数据-您将不知道您是否使用正确的数据!将连接字符串生成代码移到这个新的配置类中,以便您可以按每个请求访问它,如上面的代码示例所示。

上面的代码可能不是100%准确,因为我目前无法对其进行测试,但它足以使您到达需要的位置。