2014-08-29 59 views
1

我已經啓動了一個新的Web API項目,該項目要求我們根據發送到API的HTTP頭信息切換應用程序運行的數據庫。應用程序用戶將通過HTTP頭標識,然後應用程序應更改爲使用其數據庫。ASP.NET Web API - 基於HTTP頭信息運行更改數據庫應用程序

我有一個基礎控制器CrudControllerBase<T>(處理簡單的通用HTTP請求),它在它的構造函數中創建一個DataService<T>。我的所有控制器都將從此基礎控制器派生,並且可以訪問此DataService。 DataService用於執行常見的數據庫查詢(FindById(),FindAll()等),而更復雜的查詢則使用擴展方法。

public abstract class CrudControllerBase<T> : ApiController where T : class, IEntity 
{ 
    protected IDataService<T> _dataService; 

    public CrudControllerBase() 
    { 
     this._dataService = new DataService<T>(); 
    } 

    [HttpGet] 
    public virtual async Task<IHttpActionResult> Get(Guid id) 
    { 
     var model = await _dataService.FindByIdAsync(id); 
     return Ok<T>(model); 
    } 

    //code left out 
} 

public class OrdersController : CrudControllerBase<OrderItem> 
    { 
    } 

,並在DataService在我新出的DbContext類:

public class DataService<T> : IDataService<T> where T:class, IEntity 
{ 
    private readonly AppDbContext _context; 

    public DataService() 
    { 
     _context = new AppDbContext(); // need to pass in connection string 
    } 

    // code left out 
} 

我需要能夠在連接字符串中傳遞給AppDbContext的構造函數,但在CrudControllerBase構造我不有權訪問HttpRequestMessage以便能夠將此信息傳遞給DataService

任何人都可以提出解決方案嗎?如果有人能夠提出建議,我很樂意嘗試一種完全不同的方式。謝謝 !

+0

您可能能夠創建一個自定義控制器工廠,無論是封裝還是從DefaultControllerFactory繼承,因爲有一個重載需要RequestContext,然後你可以給你的控制器構造函數一個參數:http://www.dotnetcurry.com/showarticle.aspx?ID=878 – AaronLS 2014-08-29 23:57:39

回答

0

好的,我有這個工作。它可能不是最好的解決方案,但它的工作原理,如果任何人有任何反饋/改進,請分享。感謝@AaronLS指引我朝着正確的方向發展。這article也幫了很多。

第一步是創建一個實現IHttpControllerActivator接口的CustomControllerFactory。這給你一個Create方法,在這個方法中你可以編寫自己的代碼來創建你的控制器。這是我的CustomControllerFactory,我新我的控制器在HTTP頭傳遞作爲字符串:

public class CustomControllerFactory : IHttpControllerActivator 
{ 
    public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) 
    { 
     var schemaKey = request.Headers.Where(k => k.Key == "schema").FirstOrDefault().Value.FirstOrDefault(); 
     return (IHttpController)Activator.CreateInstance(controllerType, new string[] { schemaKey }); 
    } 
} 

下一步是要告訴web API來使用此方法實例化控制器。要做到這一點,我添加此行我WebApiConfig類:

GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new CustomControllerFactory()); 

,我需要的最後一件事是添加一個構造函數,它參加了字符串值,並將其傳遞給主控制器

public OrdersController(String databaseName) : base(databaseName) { } 
每個控制器

和我的基本控制器傳遞參數到DataService

public CrudControllerBase(String databaseName) 
{ 
    this._dataService = new DataService<T>(databaseName); 
} 

和我的數據庫通過連接字符串AppDbContext在()構造

public DataService(String databaseName) 
{ 
    this._context = new AppDbContext(BuildConnectionString(databaseName)); 
} 

我知道有沒有錯誤處理/安全檢查,但是我會補充說,:-)

+0

我有類似的場景,其中用戶有一個包含下拉列表的下拉列表要從中選擇的連接名稱。選擇實體框架必須使用該數據庫連接,直到用戶註銷。我創建了一個自定義類,它生成連接字符串以作爲實體構造函數中的參數傳遞。你可以檢查這個鏈接http://stackoverflow.com/questions/42924607/alternative-of-session-to-store-information-web-api-asp-net-project。需要幫助 – 2017-03-21 11:01:36

相關問題