2011-05-20 43 views
6

假設我正在使用新的WCF Web API來構建RESTful服務,並且在我的服務中,我有一部分URI將描述目標資源,但是用於(幾乎)合同的所有方法。舉例來說,如果我有一個用戶服務與電子商務交易,並可能看起來像:WCF Web API在多種方法中找到的UriTemplate元素

[ServiceContract] 
public class MyUserService 
{ 
    private MyUserRepository _UserRepo; 
    private MyOrganizationRepository _OrgRepo; 

    [WebGet (UriTemplate = "{OrganizationName}/Users")] 
    public IEnumerable<User> GetUsers (string OrganizationName) 
    { 
     IEnumerable<User> Users = null; 
     var Organization = _OrgRepo.GetOrgByName (OrganizationName); 

     if (Organization != null) 
     { 
      Users = Organization.GetUsers(); 
     } 
     else 
     { 
      throw new WebFaultException<string> ("Organization not found.", HttpStatusCode.NotFound); 
     } 

     return Users; 
    } 

    [WebInvoke (UriTemplate = "{OrganizationName}/Users", /*yada...yada...yada*/)] 
    public User AddNewUser (string OrganizationName, User User) 
    { 
     // Find the organization, like above, and throw if null. 
    } 
} 

如果我要不斷地加載的組織和測試空,這樣會拖垮我的代碼,是不是很乾燥。 (很想拼出DRY ...)我想要做的是在MyUserService類中加載一個屬性,該屬性在{OrganizationName}包含在URI中時填充,否則將引發WebFaultException。因爲這是URI的一部分,那麼完成此操作的最佳方法是什麼?

編輯:

對於那些可能有興趣,這裏是我想出了HttpOperationHandler的例子。這裏似乎並沒有太多的信息。我還發現有關Processors的更多信息, 將與WCF Web Api套件一起提供,看起來他們將更好地處理這種事情 替換HttpOperationHandlers,看起來它們可能更易於使用。 (這只是一個爲實例來介紹一些東西,我發現很難找到的。我在我的應用程序不同的寫了一下。)

using Microsoft.ApplicationServer.Http.Dispatcher; // For HttpOperationHandler 
using Microsoft.ApplicationServer.Http.Description; // For HttpOperationHandlerFactory 

public class OrganizationHandler : HttpOperationHandler<string, Organization> 
{ 
    private Repository<Organization> _OrganizationRepository; 

    public OrganizationHandler (UnitOfWork Work) 
     : base ("OrganizationName") 
    { 
     _OrganizationRepository = Work.Organizations; 
    } 

    public override Organization OnHandle (string OrganizationName) 
    { 
     var Result = _OrganizationRepository 
         .Get (O => O.UrlSafeName.Equals (OrganizationName, 
               StringComparison.InvariantCultureIgnoreCase)); 

     if (Result == null) 
     { 
      throw new WebFaultException<string> ("Organization not found."); 
     } 

     return Result; 
    } 
} 

public class OrganizationHandlerFactory : HttpOperationHandlerFactory 
{ 
    private UnitOfWork _Work; 

    public OrganizationHandlerFactory (UnitOfWork Work) 
    { 
     _Work = Work; 
    } 

    protected override Collection<HttpOperationHandler> OnCreateRequestHandlers 
     (ServiceEndpoint endpoint, HttpOperationDescription operation) 
    { 
     var Collection = base.OnCreateRequestHandlers (endpoint, operation); 

     if (operation.InputParameters.Any (IP => IP.Type.Equals (typeof (Organization)))) 
     { 
      var Binding = endpoint.Binding as HttpBinding; 

      if (Binding != null) 
      { 
       Collection.Add (new OrganizationHandler (_Work)); 
      } 
     } 

     return Collection; 
    } 
} 

然後在Global.asax中連線起來(我使用Ninject爲IOC):

// Add this reference to get the MapServiceRoute<T> extension 
using Microsoft.ApplicationServer.Http.Activation; 

public class Global : HttpApplication 
{ 
    protected void Application_Start (object sender, EventArgs e) 
    { 
     var Kernel = BuildKernel(); 

     var Config = HttpHostConfiguration.Create() 
      .SetOperationHandlerFactory 
       (Kernel.Get (typeof (OrganizationHandlerFactory)) as OrganizationHandlerFactory) 
      .SetResourceFactory (new NinjectResourceFactory (Kernel)); 


     RouteTable.Routes.MapServiceRoute<OrganizationService> ("Organizations", Config); 
    } 

    protected IKernel BuildKernel() 
    { 
     IKernel Kernel = new Ninject.StandardKernel(); 

     // Load up the Kernel 

     return Kernel; 
    } 
} 

public class NinjectResourceFactory : IResourceFactory 
{ 
    private readonly IKernel _Kernel; 

    public NinjectResourceFactory (IKernel Kernel) 
    { 
     _Kernel = Kernel; 
    } 

    public object GetInstance (Type serviceType, InstanceContext instanceContext, HttpRequestMessage request) 
    { 
     return Resolve (serviceType); 
    } 

    public void ReleaseInstance (InstanceContext instanceContext, object service) 
    { 
     throw new NotImplementedException(); 
    } 

    private object Resolve (Type type) 
    { 
     return _Kernel.Get (type); 
    } 
} 

這裏,它是我的服務:

[ServiceContract] 
[ServiceBehavior (InstanceContextMode = InstanceContextMode.PerCall)] 
public class OrganizationService 
{ 
    [WebGet (UriTemplate = "{OrganizationName}/Products")] 
    public IEnumerable<Product> GetProducts (Organization Organization) 
    { 
     return Organization.Products; 
    } 
} 
+0

處理器只是HttpOperationHandler的舊名稱 – 2011-05-21 00:56:55

+0

@Darrel Miller - 謝謝!我試圖跟上所有的變化,缺乏可以與其他「WCF REST」鏈接混合的信息(可以理解),這使得它變得非常困難。感謝您抓住這個! – 2011-05-21 00:59:00

+0

OperationHandler幹得不錯! – 2011-05-21 00:59:09

回答

2

這正是OperationHandlers是。您可以創建一個OperationHandler,將URI參數轉換爲強類型對象,您可以將其作爲操作的參數接受。