2015-02-09 101 views
1

多個動作我有這樣具有相同動作名稱

public ActionResult Verify(String email, String name){ 
     ViewBag.email = email; 
     ViewBag.name = name; 
     return View(); 
} 

[HttpGet] 
public ActionResult Verify(String uId){ 
     User user = TippNett.Core.User.Get(uId); 
     user.Active = true; 
     user.Save(); 
     Auth.Authenticate(user, false); 
     return RedirectToAction("Index", "Home"); 
} 

在我的控制器的多個動作的第一個動作是,當用戶註冊,以顯示他的註冊消息,請驗證電子郵件和我打電話像此

return RedirectToAction("Verify", "Account", new { email = email, name = user.FirstName}); 

當用戶單擊驗證鏈接時會調用第二個操作。 問題在於下面的函數總是被調用。即使我通過電子郵件和名稱作爲參數。

任何人都可以解釋爲什麼會發生這種情況,並可能解決這個問題?

+0

解決方法:使用不同的名稱! – DavidG 2015-02-09 13:21:11

+0

更好看看這個http://haacked.com/archive/2008/08/29/how-a-method-becomes-an-action.aspx/ – 2015-02-09 13:21:31

回答

2

您可以使用:

[ActionName("MyOverloadedName")] 

method overloading based on attribute:

[RequireRequestValue("someInt")] 
public ActionResult MyMethod(int someInt) { /* ... */ } 

[RequireRequestValue("someString")] 
public ActionResult MyMethod(string someString) { /* ... */ } 

public class RequireRequestValueAttribute : ActionMethodSelectorAttribute { 
    public RequireRequestValueAttribute(string valueName) { 
     ValueName = valueName; 
    } 
    public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) { 
     return (controllerContext.HttpContext.Request[ValueName] != null); 
    } 
    public string ValueName { get; private set; } 
} 

但是,你必須使用一個不同的動作名稱相同的HTTP方法使用不同的http方法時只能使用相同的方法。 像:

[HttpPost] 
public ActionResult Verify(String email, String name){ 
     } 

[HttpGet] 
public ActionResult Verify(String uId){ 
     User user = TippNett.Core.User.Get(uId); 
     user.Active = true; 
     user.Save(); 
     Auth.Authenticate(user, false); 
     return RedirectToAction("Index", "Home"); 
} 
+1

感謝您的解釋。 – mohsinali1317 2015-02-09 13:34:30

0

最近我拿了以進一步縮小@圖莎爾的偉大RequireRequestValueAttribute讓它支持更多的場景,比如多參數的支持和不同類型的比賽,將觸發它的機會:所有給定的參數,其中任何一個,甚至沒有。

我打電話給新版本RequiredParameterAttribute,我在所有最終使用的MVC項目中都使用它。

下面是完整的源代碼:

/// <summary> 
/// Flags an Action Method valid for any incoming request only if all, any or none of the given HTTP parameter(s) are set, 
/// enabling the use of multiple Action Methods with the same name (and different signatures) within the same MVC Controller. 
/// </summary> 
public class RequireParameterAttribute : ActionMethodSelectorAttribute 
{ 
    public RequireParameterAttribute(string parameterName) : this(new[] { parameterName }) 
    { 
    } 

    public RequireParameterAttribute(params string[] parameterNames) 
    { 
     ParameterNames = parameterNames; 
     IncludeGET = true; 
     IncludePOST = true; 
     IncludeCookies = false; 
     Mode = MatchMode.All; 
    } 

    public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) 
    { 
     switch (Mode) 
     { 
      case MatchMode.All: 
      default: 
       return (
        (IncludeGET && ParameterNames.All(p => controllerContext.HttpContext.Request.QueryString.AllKeys.Contains(p))) 
        || (IncludePOST && ParameterNames.All(p => controllerContext.HttpContext.Request.Form.AllKeys.Contains(p))) 
        || (IncludeCookies && ParameterNames.All(p => controllerContext.HttpContext.Request.Cookies.AllKeys.Contains(p))) 
        ); 
      case MatchMode.Any: 
       return (
        (IncludeGET && ParameterNames.Any(p => controllerContext.HttpContext.Request.QueryString.AllKeys.Contains(p))) 
        || (IncludePOST && ParameterNames.Any(p => controllerContext.HttpContext.Request.Form.AllKeys.Contains(p))) 
        || (IncludeCookies && ParameterNames.Any(p => controllerContext.HttpContext.Request.Cookies.AllKeys.Contains(p))) 
        ); 
      case MatchMode.None: 
       return (
        (!IncludeGET || !ParameterNames.Any(p => controllerContext.HttpContext.Request.QueryString.AllKeys.Contains(p))) 
        && (!IncludePOST || !ParameterNames.Any(p => controllerContext.HttpContext.Request.Form.AllKeys.Contains(p))) 
        && (!IncludeCookies || !ParameterNames.Any(p => controllerContext.HttpContext.Request.Cookies.AllKeys.Contains(p))) 
        ); 
     } 
    } 

    public string[] ParameterNames { get; private set; } 

    /// <summary> 
    /// Set it to TRUE to include GET (QueryStirng) parameters, FALSE to exclude them: 
    /// default is TRUE. 
    /// </summary> 
    public bool IncludeGET { get; set; } 

    /// <summary> 
    /// Set it to TRUE to include POST (Form) parameters, FALSE to exclude them: 
    /// default is TRUE. 
    /// </summary> 
    public bool IncludePOST { get; set; } 

    /// <summary> 
    /// Set it to TRUE to include parameters from Cookies, FALSE to exclude them: 
    /// default is FALSE. 
    /// </summary> 
    public bool IncludeCookies { get; set; } 

    /// <summary> 
    /// Use MatchMode.All to invalidate the method unless all the given parameters are set (default). 
    /// Use MatchMode.Any to invalidate the method unless any of the given parameters is set. 
    /// Use MatchMode.None to invalidate the method unless none of the given parameters is set. 
    /// </summary> 
    public MatchMode Mode { get; set; } 

    public enum MatchMode : int 
    { 
     All, 
     Any, 
     None 
    } 
} 

我保留了「老」簽名,以便它可以用來就像以前的分期付款。

有關更多信息和一些實施示例,您還可以閱讀this post