2014-03-18 55 views
0

我希望獲得關於將自定義對象從「REST」服務器傳輸到控制器的最佳方法的建議。簡而言之,我們在處理HttpGet請求的服務器上運行MVC 4。最初,來自服務器的所有響應都可以通過將我們的自定義類序列化爲JSON,然後反序列化它們的客戶端大小來適應。但是,現在我們需要傳輸大量數據(即圖像),這種方法不再有效。如何從REST服務器向控制器傳輸大類類型

以下是我目前正在做的精簡版本,但我希望有更好的方式來傳輸大型文件(自定義類型)的一些建議。

類:

[Serializable] 
public class TradingPost 
{ 
    public int TradingPostId { get; set; } 
    public string UserId { get; set; }   
} 

[Serializable] 
public class TradingPostImage 
{ 
    public int TradingPostImageId { get; set; } 
    public string ImageName { get; set; } 
    public string ImageData { get; set; } 
} 

[Serializable] 
public class TradingPostWithImages 
{ 
    public TradingPost Post { get; set; } 
    public List<TradingPostImage> Images { get; set; } 

    public TradingPostWithImages() 
    { 
     Post = new TradingPost(); 
     Images = new List<TradingPostImage>(); 
    } 
} 

服務器側控制器:

[HttpGet] 
    public ActionResult GetAllTradingPosts() 
    {    
     List<TradingPostWithImages> postsAndImages = PostRepository.GetAllPostsAndImages(); 

     MemoryStream memoryStream = new MemoryStream(); 
     BinaryFormatter binaryFormatter = new BinaryFormatter(); 
     binaryFormatter.Serialize(memoryStream, postsAndImages); 

     var postsAsByteArray = memoryStream.ToArray(); 

     return File(postsAsByteArray, "application/octet-stream");    
    } 

客戶端控制器:

public List<TradingPostWithImages> GetItems() 
    { 
     var dataGatewayPath = GetGateWayPath("GetTradingPosts"); 

     MemoryStream webData = new MemoryStream(); 

     var Request = WebRequest.CreateHttp(dataGatewayPath); 
     var Response = Request.GetResponse() as HttpWebResponse; 

     if(Response != null) 
     { 
      DataStream = Response.GetResponseStream(); 

      if(DataStream != null) 
      { 
        DataStream.CopyTo(webData); 
        DataStream.Close(); 
      } 

      Response.Close(); 
     } 

     webData.Position = 0; 
     BinaryFormatter formatter = new BinaryFormatter(); 

     var activeItems = (List<TradingPostWithImages>)formatter.Deserialize(webData); 

     return activeItems; 
    } 

這個工作,但有什麼辦法,我可以做到什麼,我以後沒有反序列化一個流,然後將其轉換爲我的自定義類型?是否有更好或更有效的方式來完成我的任務?

+0

是的,只需堅持json/xml並讓您的REST服務器返回一個圖像編碼爲base64的對象。另外,不要在控制器上執行數據層邏輯:) – Sinaesthetic

+0

或者我在這種情況下做的一般是在第一遍中返回帶有圖像標識符的對象列表,然後讓端點獲取圖像標識並檢索來自服務器的圖像並在事實(例如)之後加載它們,其中內容控制器上的圖像操作請求來自服務器的具有ID「abcd」的圖像。這會給你一個更快的初始響應,並允許圖像異步加載。這有點煩人,但在客戶端更好的表現。 – Sinaesthetic

+0

@Sinaesthetic感謝您的反饋。對於非常大的圖像,您如何應對maxJsonLength問題?只需將值設得很高?呵呵,不用擔心控制器中的邏輯問題,這個例子是一個「精簡版」,我認爲這個版本更容易發佈。 – D0ubleGunz

回答

1

要根據評論中的一些對話直接回答你的問題,真的,我可以建議的唯一事情就是你採取了懶惰的加載類型方法。通常,在延遲加載的情況下,您可以根據需要加載數據,但在這種情況下,所有數據都將立即需要使用,但這一想法完全相同。所以我建議的最有效的方式是首先加載所有簡單的數據(基本上數據傳輸速度相當快,在這種情況下,幾乎所有的東西都是圖像)。我不認爲你會比http上的字節流更有效率(也許嘗試UDP ??),所以可以通過用戶感知來調整性能。

如果您的視圖圖層是網頁,那麼您可以首先渲染所有基本對象數據,方法是在第一次調用時引用瘦對象中的圖像ID(而不是發送包含圖像數據的胖對象) ,然後將這些ID用於圖像標籤,然後調用內容操作,該操作將使用該ID異步地從服務器檢索圖像數據。這樣,即使在圖像加載時,您的頁面也可以使用。像這樣:

enter image description here

如果您的視圖層是像WinForms應用程序,你可以做大致相同的事情。這個想法是,當圖像加載到不同的線程時,即時檢索並顯示簡單的數據,保持UI的響應。只顯示圖像即將顯示的某種加載指示器。

國際海事組織,當通過HTTP發生大型文件傳輸時,只有很多你可以做[創造性]高效。更重要的是處理與重試邏輯的中斷連接(恢復下載,通過字節偏移量等),並保持UI比其他任何響應。只要沒有用戶感覺應用程序被鎖定的情況下正在取得可見的進展,那麼由這些冗長的加載時間造成的負面經歷應該被減輕。

因此,除了這個消息傳遞策略之外,我只是研究流技術。本文可能有所幫助:WebAPI Request Streaming support