0

在我的ASP.NET MVC應用程序,我想實現以下概念:如何區分ASP.NET MVC 4控制器中初始模型的空模型?

  • 瀏覽http://.../PersonData/Show?id=A5668A31-9AAC-4A14-B471-7C9BA236961D應顯示由指定ID標識的人的數據。
  • 瀏覽http://.../PersonData/Show應顯示一個窗體的視圖,我可以在文本框中輸入一個ID。當我提交表單時,瀏覽器應該導航但不能發佈到上面給出的URL(即表單的方法設置爲GET)。
  • 當我在未輸入ID的情況下提交表單(導致瀏覽URL爲http://.../PersonData/Show?id=)時,ASP.NET MVC模型驗證應顯示一條消息,指出該ID是必需的。 (有或沒有JavaScript被啓用。)

要實現這一點,我建立這樣一個模型:

class Model 
{ 
    [Required] 
    public Guid? Id { get; set; } 
} 

現在我有問題,對於第一次,ASP瀏覽http://.../PersonData/Show時。 NET模型驗證立即給出了一個錯誤,該ID是必需的,因爲它不區分表單沒有提交ID的情況(?id=)和第一次調用該操作的情況(根本沒有提供ID )。

想法我有:

  • 使用兩個不同的控制器動作和URL(如http://.../PersonData/Searchhttp://.../PersonData/Show?id=)先瀏覽和空表單提交區分。
  • 使用額外的表單參數(如http://.../PersonData/Showhttp://.../PersonData/Show?valueGiven=true&id=)。
  • 使用Request對象檢查操作方法中的URL參數,並清除"id"中的ModelState錯誤(如果該關鍵字不存在於URL中)。

解決這個問題的最佳方法是什麼?有更好的第四種方法嗎?

(有一兩件事,沒有工作是添加有兩個名稱相同的動作方法GET操作:

[HttpGet] 
public void Show() { /* return view with initial browsing logic */ } 
[HttpGet] 
public void Show(Model model) { /* return view with subsequent browsing logic */ } 

這似乎並沒有被通過ASP.NET MVC允許)

更新2013-06-25:對不起,我的示例中有兩個錯誤,ID應該是Guid,而不是字符串;當然,我在我的操作方法中綁定了模型,因爲我需要Required屬性進行評估。

這是我的路由配置:

public static void RegisterRoutes (RouteCollection routes) 
{ 
    routes.IgnoreRoute ("{resource}.axd/{*pathInfo}"); 

    routes.MapRoute (
     name: "Default", 
     url: "{controller}/{action}", 
     defaults: new { controller = "Home", action = "Index" } 
); 
} 
+0

能告訴你的路線配置?看起來路由中的ID不是可選的! – Fals

回答

1

如果我打算有兩種方法爲GET,那麼我更喜歡你的第一種方法:一個搜索頁面和搜索結果頁與傳遞的參數如果我希望用戶共享鏈接,這是我喜歡採取的方法,因爲所有參數都將位於查詢字符串中。

另一方面,如果共享不是真的問題,我希望有一個GET方法來顯示錶單,然後將其提交給具有相同名稱的POST方法的操作方法。

1

如果你沒有通過ID,則ID將是無效的。如果你通過一個值id,id將是「」(即,空字符串.. String.Empty)

因此,您不能使用Required屬性,因爲這會產生錯誤。您必須在控制器中手動檢查值。

更好的方法是創建一個特殊的路由來使用路由約束來處理帶有id的版本。此路由中的id不會是可選的,但是約束會阻止沒有選擇id的路由。

我現在沒有能力爲你創建和測試這個案例,但是這應該給你一些東西繼續下去。也許別人可以掀起一些東西。

在路線約束的信息可以在這裏找到:

http://www.asp.net/mvc/tutorials/controllers-and-routing/creating-a-route-constraint-cs

+0

謝謝,你是對的,使用一個字符串(並省略Required屬性)我可以手動檢查。但是,我在原始問題文本中犯了一個錯誤,實際上有一個'Guid?' - 在這種情況下,沒有區別的第三個值(模型綁定器將「空」情況綁定到null)。省略'RequiredAttribute'意味着我還必須手動附加客戶端驗證,所以這是不幸的(但當然可能)。 –

+0

關於路由約束:'id'作爲URL參數傳遞(因爲它是一個帶GET方法的HTML表單)。我無法創建基於此的路線,我可以嗎?如果是這樣,怎麼樣? –

0

只需添加一個if情況下您最初的放映功能

[HttpGet] 
public void Show(int? id) { 

    if(id.HasValue) { 
    /* return view with subsequent browsing logic */ 
    } 
    else { 
     /* return view with initial browsing logic */ 
    } 
} 

編輯: 這可能工作

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 
    public class RequestMatchAnyAttribute : ActionNameSelectorAttribute 
    { 
     public string MatchFormKey { get; set; } 

     public RequestMatchAnyAttribute(string matchAnyFormKeys) 
     { 
      this.MatchFormKey = matchAnyFormKeys; 
     } 

     public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo) 
     { 
      return controllerContext.HttpContext.Request[MatchFormKey] != null; 
     } 
    } 


[HttpGet] 
public void Show() { 
    /* default view */ 
} 

[ActionName("Show")] 
[RequestMatchAny("Id")] 
[HttpGet] 
public void ShowEdit(int? id) { 

    if(id.HasValue) { 
    /* return edit view */ 
    } 
    else { 
     /* return create view */ 
    } 
} 
+0

這不是我所需要的 - 我需要區分三種情況:初始brwosing,隨後使用id給出的瀏覽以及隨後的未給定id的瀏覽。 (請注意,在我的原始問題文本中有兩個錯誤。) –

+0

@FabianSchmied爲什麼不使用不同的動作爲列表和一個爲創建/編輯 – Kyle

+0

當然,這是我的問題的第一個選項:) 我只是想看看是否有更好的選擇。 –