2013-01-06 16 views
0

我有一種情況,從第二次調用和後續調用(Ajax GET調用)開始,AutoMapper正在重用之前的值(第一次調用的值來自操作鏈接中的單擊)。它就像一個「緩存」的問題......AutoMapper UseValue,ResolveUsing或MapFrom重用先前調用的值。它是緩存還是什麼?

public virtual ActionResult List(int assessmentId, int? chapterId, bool? isMenuClick) 
{ 

    Mapper.CreateMap<Element, AssessmentQuestionViewModel>(). 
    ForMember(dest => dest.AssessmentId, opt => opt.MapFrom(e => assessmentId)); 

    ... 

} 

,如果我在上面opt =>拉姆達使用UseValueResolveUsingMapFrom沒關係。行爲是相同的,也就是說,它重用了以前調用的值。

AssessmentId屬性在源類型中不存在(Element)。通過這種方式,我嘗試將AssessmentId的值指定爲「可能」在隨後調用具有此代碼的方法期間動態更改的值。 assessmentId是我的ASP.NET MVC操作方法中的一個參數,如上面在方法簽名中所示。

然後我把這個代碼在List操作方法:

var questions = 
    Mapper.Map<IEnumerable<Element>, IEnumerable<AssessmentQuestionViewModel>> 
    (Database.Elements.Where(e => !elementIds.Contains(e.ElementId) && 
           e.Standard.ChapterId == chapterId)); 

第一次,questions是確定的,那就是,所有AssessmentQuestionViewModel對象具有AssessmentId屬性設置正確按規定的CreateMap

從第二個呼叫開始,它重新使用第一個呼叫的assessmentId,並將它與我的業務邏輯,因爲我希望它映射到AssessmentId更新assessmentId多數民衆贊成被作爲參數傳遞給List方法傳遞攪亂。

可以肯定的是:我在代碼中設置了一個斷點,我可以看到assessmentId參數的值是正確的。這只是返回的映射對象questionsAssessmentId屬性中具有錯誤的值 - 與當前assessmentId值不同的值。因爲我要求AutoMapper使用當前值進行映射,所以值應該相等。

我有AutoMapper 2.2.1-ci9000(預發佈),但我測試了這個與以前的版本,我看到了這種相同的行爲。我更新了預發行版,認爲這種「不當行爲」將會消失。

我認爲這是一個錯誤。如果我錯了,或者我嘗試以不支持的方式使用它,請糾正我。 :)

+2

CreateMap應該爲每個AppDomain調用一次 - 不在您的控制器操作中。這不是它被緩存 - 而是它不會被重新配置。單。時間。 –

+0

@JimmyBogard所以在我的具體情況下,我應該遵循什麼樣的路徑?每次調用操作方法時,我都必須在目標對象中手動設置該特定屬性?現在我用一個簡單的'foreach' ... –

回答

4

我認爲這裏的問題你試圖創建相同類型的多個映射 - 哪些AutoMapper不支持。每次調用List操作時,都會創建一個新的映射(它具有不同的ForMember(...)子句)。 AutoMapper不會拋出異常它只是忽略重複的映射,所以你在這裏看到的不是一個錯誤,它是預期的行爲。

ForMember事實上稱爲地圖,但是,由於變量是硬編碼到表達式中的,因此您在此處有一個範圍問題。作爲變通,你可以這樣做:

public class MyController 
{ 
    public MyController() 
    { 
     // define mapping once, but make assessment expression dynamic 
     Mapper.CreateMap<Element, AssessmentQuestionViewModel>(). 
      ForMember(dest => dest.AssessmentId, opt => opt.MapFrom(e => GetCurrentAssessmentId())); 
    } 

    private int GetCurrentAssessmentId() 
    { 
     return (int)TempData["AssessmentId"]; 
    } 

    public ActionResult List(int assessmentId, ...) 
    { 
     // store current assessment temporarily 
     TempData.Add("AssessmentId", assessmentId); 
     // execute mapping 
     var questions = Mapper.Map<IEnumerable<Element>, IEnumerable<AssessmentQuestionViewModel>> 
(Database.Elements.Where(e => !elementIds.Contains(e.ElementId) && 
          e.Standard.ChapterId == chapterId)); 
    } 
} 

我會說,雖然,你的跳躍通過大量的籃球這個來工作,這將是更簡單的手動設置屬性,而不AutoMapper的幫助例如

var questions = Mapper.Map<IEnumerable<Element>, IEnumerable<AssessmentQuestionViewModel>>(...); 
foreach (var q in questions) 
{ 
    q.AssessmentId = assessmentId; 
} 
+0

呃...我想我明白你在說什麼。那麼,你有什麼想法我應該如何處理這個映射?我需要爲'Mapper.CreateMap'分配動態值。根據你的說法,我只能定義一次'CreateMap'。也許我可以這樣做:'if(!isMenuClick.HasValue){// CreateMap,因爲它是第一次調用action方法}',然後對於後續調用(Ajax調用),我只需調用Mapper.Map。 –

+0

上面沒有工作...... :( –

+0

@LenielMacaferi看到我的更新。這裏的目標是使評估Id動態的初始映射(所以沒有硬編碼的表達式)。一個簡單的方法做到這一點就是從函數返回它 – James

相關問題