2015-01-15 119 views
3

我目前正在努力在WebApi中繼承工作,就像我想。 也許你可以指出我正確的方向?Asp.Net WebApi繼承與基本控制器

我的目標是擁有一個通用的WebApi項目,它可以在多個其他WebApi項目中重用。

例如:我有一個可重用的UserController,它可以處理多個WebSites的登錄。現在我構建一個新的WebSite並簡單地將UserController添加到新創建的項目中,該項目很簡單。

但是現在對新網站的要求發生了變化,我需要重載UserController方法以反映這些更改而不修改通用控制器。

我想實現可以在下面的代碼片段中看到什麼(當然這不能編譯,因爲C#抱怨沒有合適的方法超載找到。)

// This belongs to solution "GenericWebApi" 

public class LoginRequest 
{ 
    public string User { get; set; } 
} 

public class BaseApiController : ApiController 
{ 
    [Route("login")] 
    public virtual HttpResponseMessage Login(LoginRequest request) 
    { 
     return new HttpResponseMessage(); 
    } 
} 


// This belongs to solution "CarWebsite" 

public class CarWebsiteLoginRequest : LoginRequest 
{ 
    public string Car { get; set; } 
} 

[RoutePrefix("api/users")] 
public class CarWebsiteApiController : BaseApiController 
{ 
    public override HttpResponseMessage Login(CarWebsiteLoginRequest request) 
    { 
     // Do some car specific login stuff 
     return base.Login(request); 
    } 
} 

一個解決方案,我發現是工作正在用「動態」取代「LoginRequest」和「CarWebsiteLoginRequest」,但感覺簡直是錯誤的,ModelBinder當然不會按預期工作。

任何想法你會如何解決?

在此先感謝

回答

7

你可以讓你BaseApiController通用:

public class BaseApiController<TLoginRequest> : ApiController 
where TLoginRequest : LoginRequest 
{ 
    [Route("login")] 
    public virtual HttpResponseMessage Login(TLoginRequest request) 
    { 
     return new HttpResponseMessage(); 
    } 
} 

,使您的CarWebsiteApiController使用CarWebsiteLoginRequest作爲一種通用的參數:

public class CarWebsiteApiController : BaseApiController<CarWebsiteLoginRequest> 
{ 
    public override HttpResponseMessage Login(CarWebsiteLoginRequest request) 
    { 
     // Do some car specific login stuff 
     return base.Login(request); 
    } 
} 
+0

感謝您的建議,這似乎是一個不錯的方法。 但是我的BaseApiController會有> 10-15個WebApi操作。所以我需要使它BaseApiController 。你還有其他方式嗎? – coalmee

0

如果拔出變量,在方法內部讀取它更容易過載

/// <summary> 
/// Notice name is not Controller.cs This would expose this API if the name ended in controller 
/// </summary> 
public class GenericControllerApi : ApiController 
{ 
    protected JavaScriptSerializer JsonReader = new JavaScriptSerializer(); 

    [HttpPost] 
    public virtual HttpResponseMessage Login() 
    { 
     string JsonRequest = Request.Content.ReadAsStringAsync().Result; 

     LoginRequest JSONData = null; 
     try 
     { 
      JSONData = (LoginRequest)JsonReader.Deserialize(JsonRequest, typeof(LoginRequest)); 
     } 
     catch { } 

     if (JSONData != null) 
     { 
      if (CommonUserCalls(JSONData.User)) 
      { 
       ShowUser UserReturn = new ShowUser(); 
       UserReturn.UserName = "BaseUser"; 
       return Request.CreateResponse(HttpStatusCode.OK, UserReturn); 
      } 

      return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid User"); 
     } 
     else 
     { 
      return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "ShowUser not provided"); 
     } 
    } 

    protected bool CommonUserCalls(string User) 
    { 
     if (User == "MyUser") 
     { 
      return true; 
     } 
     return false; 
    } 

    public class LoginRequest 
    { 
     public string User { get; set; } 
    } 

    protected class ShowUser 
    { 
     public string UserName { get; set; } 
    } 
} 

public class CarController : GenericControllerApi 
{ 
    [HttpPost] 
    public override HttpResponseMessage Login() 
    { 
     string JsonRequest = Request.Content.ReadAsStringAsync().Result; 

     CarWebsiteLoginRequest JSONData = null; 
     try 
     { 
      JSONData = (CarWebsiteLoginRequest)JsonReader.Deserialize(JsonRequest, typeof(CarWebsiteLoginRequest)); 
     } 
     catch { } 

     if (JSONData != null) 
     { 
      if (CommonUserCalls(JSONData.User)) 
      { 
       ShowUser UserReturn = new ShowUser(); 
       UserReturn.UserName = "CarUser"; 
       return Request.CreateResponse(HttpStatusCode.OK, UserReturn); 
      } 

      return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Invalid User"); 
     } 
     else 
     { 
      return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "CarWebsiteLoginRequest not provided"); 
     } 
    } 

    public class CarWebsiteLoginRequest : LoginRequest 
    { 
     public string Car { get; set; } 
    } 
} 

假設您正在閱讀/發送JSON

+0

感謝您的建議。這似乎沒有比使用「動態」(使用JObject例如用於序列化)提供好處。此外,您的解決方案添加了大量重複的代碼,似乎再沒有使用通用控制器的真正意義。 – coalmee

+0

這個快速示例顯示如何重載基本調用,重構以根據需要進行優化。任何通用代碼都應放置在受保護的方法中。我已編輯以顯示此內容。 –

+0

我想更多地使用@Sergey方法,以利用ModelBinder等。您的解決方案不允許我使用他們打算使用的WebApi功能(可插入序列化程序,模型驗證等) – coalmee