2013-01-21 95 views
0

我正在設置自定義屬性來保護視圖中的對象。這裏是我的自定義屬性的定義:OnMetadataCreated多次執行

這裏是我的視圖模型:用於安全標籤和安全文本框

public class HomeViewModel 
{ 
    [SecureObject(ObjectId = 1)] 
    [Display(Name = "Name")] 
    public string Name { get; set; } 

    [Display(Name = "Address")] 
    public string Address { get; set; } 
} 

我定義的幫手。這裏是我的輔助功能:

public static MvcHtmlString SecureLabelFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression) 
    { 
     var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); 
     if ((bool)metadata.AdditionalValues["isSecure"]) 
     { 
      return null; 
     } 
     else 
     { 
      return html.LabelFor(expression); 
     } 
    } 

    public static MvcHtmlString SecureTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression) 
    { 
     var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData); 
     if ((bool)metadata.AdditionalValues["isSecure"]) 
     { 
      return null; 
     } 
     else 
     { 
      return html.TextBoxFor(expression); 
     } 
    } 

所有這一切工作正常,但是,我遇到的問題是,每次我定義一個安全標籤和安全的文本框時,OnMetadataCreated方法被調用。

我正在訪問OnMetadataCreated方法(未在此示例中顯示)上的數據庫以獲取對象的權限,並且我希望避免單個對象的重複行程。

下面是導致OnMetadataCreated要在我看來,兩次調用的代碼示例:

 

    @Html.SecureLabelFor(m => m.Name) 
    @Html.SecureTextBoxFor(m => m.Name) 

我如何能避免OnMetadataCreated方法的第二個電話,或避免重複任何建議旅行到數據庫?

+0

在哪些變量並調用數據庫的依賴?你傳遞給你的查詢的參數是什麼,它們在用戶和會話之間有什麼不同? –

+0

對數據庫的調用取決於ObjectId和當前登錄的用戶。我從數據庫中獲取isSecure值。 – TK1

+0

如何在OnMetadataCreated方法中獲取當前登錄的用戶? –

回答

0

你可以存儲在HttpContext的查詢的執行,以避免在同一個請求中往返到數據庫的結果:

public void OnMetadataCreated(ModelMetadata metadata) 
{ 
    // TODO: if you are using a DI framework you could pass the context 
    // as a constructor argument dependency and use HttpContextBase 
    HttpContext context = HttpContext.Current; 

    bool isSecure; 
    string key = "isSecure_" + ObjectId; 
    if (context.Items.Contains(key)) 
    { 
     // The isSecure value was found in the HttpContext => 
     // no need to query the database once again within this request 
     isSecure = (bool)context.Items[key]; 
    } 
    else 
    { 
     // Get the value from the database 
     isSecure = GetFromDb(context.User.Identity.Name, ObjectId); 
     // and store into the HttpContext to avoid roundtrips to the database 
     // within this request 
     context.Items[key] = isSecure; 
    } 

    ... 
} 
+0

如果我的ViewModel中有多個項目需要保護,這對我無效。 如果我在ViewModel中的地址對象的頂部添加[SecureObject(ObjectId = 2)],並在我的視圖中添加: @ Html.SecureLabelFor(m => m.Address) @ Html.SecureTextBoxFor m => m.Address) 任何進一步的幫助,將不勝感激。 – TK1

+0

製作一個可以包含ObjectId的複雜鍵。因此,不要使用'context.Items [「isSecure」]'使用'context.Items [「isSecure_」+ ObjectId]'。我已經更新了我的答案以說明這一點。現在,您將針對每個使用幫助器的唯一'ObjectId'的相同請求來訪問數據庫。 –

+0

好吧,我明白你要在這裏做什麼。我現在得到的問題是我的幫助函數被定義爲靜態的,我的ObjectId被定義爲ViewModel中的屬性。我將如何獲得助手中的ObjectId?我只想渲染不安全的標籤或文本框。 – TK1