2013-04-08 63 views
1

在獨立模式下使用ServiceStack時,我在Apphost中爲任意文件名(它只是將數據文件從數據目錄中提取出來)中定義了一個catch-all處理程序。ServiceStack:在處理程序中設置響應類型?

其核心的方法是(fiFileInfo成員變量,和ExtensionContentType是從擴展到MIME類型一個Dictionary):

public class StaticFileHandler : EndpointHandlerBase 
{ 
    protected static readonly Dictionary<string, string> ExtensionContentType; 

    protected FileInfo fi; 

    static StaticFileHandler() 
    { 
     ExtensionContentType = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) 
     { 
      { ".text", "text/plain" }, 
      { ".js", "text/javascript" }, 
      { ".css", "text/css" }, 
      { ".html", "text/html" }, 
      { ".htm", "text/html" }, 
      { ".png", "image/png" }, 
      { ".ico", "image/x-icon" }, 
      { ".gif", "image/gif" }, 
      { ".bmp", "image/bmp" }, 
      { ".jpg", "image/jpeg" } 
     }; 
    } 

    public string BaseDirectory { protected set; get; } 
    public string Prefix { protected set; get; } 

    public StaticFileHandler(string baseDirectory, string prefix) 
    { 
     BaseDirectory = baseDirectory; 
     Prefix = prefix; 
    } 

    private StaticFileHandler(FileInfo fi) 
    { 
     this.fi = fi; 
    } 

    public static StaticFileHandler Factory(string baseDirectory, string prefix, string pathInfo) 
    { 
     if (!pathInfo.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) 
     { 
      return null; 
     } 

     var fn = baseDirectory + "/" + pathInfo.After(prefix.Length); 

     Console.Write("StaticFileHandler.Factory fn=" + fn); 

     Console.WriteLine("AbsoluteUri={0}", pathInfo); 

     var fi = new System.IO.FileInfo(fn); 

     if (!fi.Exists) 
     { 
      return null; 
     } 

     return new StaticFileHandler(fi); 
    } 

    public override void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName) 
    { 
     using (var source = new System.IO.FileStream(fi.FullName, System.IO.FileMode.Open)) 
     { 
      source.CopyTo(httpRes.OutputStream); 
      //var bytes = source.ReadAllBytes(); 
      //httpRes.OutputStream.Write(bytes, 0, bytes.Length); 
     } 

     // timeStamp = fi.LastWriteTime;       

     httpRes.AddHeader("Date", DateTime.Now.ToString("R")); 
     httpRes.AddHeader("Content-Type", ExtensionContentType.Safeget(fi.Extension) ?? "text/plain"); 
     //httpRes.ContentType = ExtensionContentType.Safeget(fi.Extension, "text/plain"); 
    } 

    public override object CreateRequest(IHttpRequest request, string operationName) 
    { 
     return null; 
    } 

    public override object GetResponse(IHttpRequest httpReq, IHttpResponse httpRes, object request) 
    { 
     return null; 
    } 
} 

實際HTTP響應-Type頭沒有被置位時,我使用標記爲方法1或方法2的行進行運行。使用IE9開發人員工具進行調試顯示,根本沒有設置響應類型。

從catch-all處理程序設置內容類型(和流內容)的正確方法是什麼?

這不是一個標準的服務,所以我不能只返回一個自定義的IHttpResponse這似乎是正常的服務方法。

附加信息:Date頭沒有被設置要麼...

+0

什麼類/方法是您的ProcessRequest方法重寫?我認爲這將是AppHostHttpListenerBase.ProcessRequest,但您的示例接受更多的參數。另外,你可以嘗試調用httpRes.EndServiceStackRequest()來結束請求。 – paaschpa 2013-04-08 20:38:28

+0

@paaschpa我已更新源代碼以包含完整的課程。它從'EndpointHandlerBase'繼承。響應正在發送到瀏覽器就好了,除了我的自定義標題不在其中。 – SAJ14SAJ 2013-04-08 20:43:05

回答

2

我認爲這個問題是這一行,如果你這樣做

public override void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName) 
{ 
    var bytes = File.ReadAllBytes(fi.FullName);     
    httpRes.AddHeader("Date", DateTime.Now.ToString("R")); 
    httpRes.AddHeader("Content-Type", "text/plain"); 
    httpRes.AddHeader("TestHeader", "SomeValue"); 
    httpRes.OutputStream.Write(bytes, 0, bytes.Length); 
} 
source.CopyTo(httpRes.OutputStream);

標題應填入

簡單的控制檯應用程序測試答案

Initialize ServiceStack Ap pHost和控制檯內運行:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var appHost = new AppHost(); 
     appHost.Init(); 
     appHost.Start("http://*:1337/"); 
     System.Console.WriteLine("Listening on http://localhost:1337/ ..."); 
     System.Console.ReadLine(); 
     System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite); 
    } 
} 

一些虛擬服務...不是真的有必要對這樣的回答:

[Route("/Hello/{Name}")] 
public class Hello 
{ 
    public string Name { get; set; } 
} 

public class HelloService : Service 
{ 
    public string Any(Hello request) 
    { 
     return request.Name; 
    } 
} 

配置APPHOST和「測試代碼」添加到CatchAllHanders:

public class AppHost : AppHostHttpListenerBase 
{ 
    public AppHost() : base("Test Console", typeof(AppHost).Assembly) { } 

    public override void Configure(Funq.Container container) 
    { 
     CatchAllHandlers.Add(StaticFileHandler.Factory); 
    } 

} 

修改 '測試代碼' - 主要是需要去的ProcessRequest(),並返回一個文件:

public class StaticFileHandler : EndpointHandlerBase 
{ 
    protected static readonly Dictionary<string, string> ExtensionContentType; 

    protected FileInfo fi; 

    static StaticFileHandler() 
    { 
     ExtensionContentType = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) 
    { 
     { ".text", "text/plain" }, 
     { ".js", "text/javascript" }, 
     { ".css", "text/css" }, 
     { ".html", "text/html" }, 
     { ".htm", "text/html" }, 
     { ".png", "image/png" }, 
     { ".ico", "image/x-icon" }, 
     { ".gif", "image/gif" }, 
     { ".bmp", "image/bmp" }, 
     { ".jpg", "image/jpeg" } 
    }; 
    } 

    public string BaseDirectory { protected set; get; } 
    public string Prefix { protected set; get; } 

    public StaticFileHandler(string baseDirectory, string prefix) 
    { 
     BaseDirectory = baseDirectory; 
     Prefix = prefix; 
    } 

    private StaticFileHandler(FileInfo fi) 
    { 
     this.fi = fi; 
    } 

    public static StaticFileHandler Factory(string baseDirectory, string prefix, string pathInfo) 
    { 
     return new StaticFileHandler(new FileInfo(@"C:\Test.xml")); 
    } 

    public override void ProcessRequest(IHttpRequest httpReq, IHttpResponse httpRes, string operationName) 
    { 
     var bytes = File.ReadAllBytes(fi.FullName); 

     httpRes.AddHeader("Date", DateTime.Now.ToString("R")); 
     httpRes.AddHeader("Content-Type", "text/plain"); 
     httpRes.AddHeader("Test", "SetThis"); 

     httpRes.OutputStream.Write(bytes, 0, bytes.Length); 
    } 

    public override object CreateRequest(IHttpRequest request, string operationName) 
    { 
     return null; 
    } 

    public override object GetResponse(IHttpRequest httpReq, IHttpResponse httpRes, object request) 
    { 
     return null; 
    } 
} 
+0

我已經有AddHeader()調用,他們不工作。或者你是在暗示這是依賴於順序的。 – SAJ14SAJ 2013-04-08 22:14:42

+0

嘗試在寫入內容流之前放入'AddHeader'調用;行爲沒有變化。 – SAJ14SAJ 2013-04-08 22:19:38

+0

您是否刪除了source.CopyTo(httpRes.OutputStream);呼叫?我在一個簡單的控制檯AppHost中添加了我的完整測試,它是您示例的修改版本。 – paaschpa 2013-04-08 22:25:24

相關問題