2009-10-21 6 views
5

Eigentlich habe ich eine Anwendung, die einen WebService verwendet, um einige Client-Informationen abzurufen. So wurde ich Validieren der Anmeldeinformationen in meinem Action wie:ASP.NET MVC - ActionFilterAttribute, um POST-Daten zu validieren

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult ClientLogin(FormCollection collection) 
{ 
    if(Client.validate(collection["username"], collection["password"])) 
    { 
     Session["username"] = collection["username"]; 
     Session["password"] = collection["password"]; 
     return View("valid"); 
    } 
    else 
    { 
     Session["username"] = ""; 
     Session["password"] = ""; 
     return View("invalid"); 
    } 
} 

Wo Client.Validate() ist eine Methode, die einen Booleschen Wert zurück, basierend auf den Informationen über den Benutzernamen und das Kennwort POST bereitgestellt

Aber ich änderte meine Meinung und ich würde gerne dieses nette ActionFilterAttributes am Anfang der Methode verwenden, so dass es nur gerendert wird, wenn das Client.validate() true zurückgibt, genauso wie [Authorize], aber mit meinem eigenen Webservice, also würde ich es tun habe etwas wie:

[AcceptVerbs(HttpVerbs.Post)] 
[ValidateAsClient(username=postedUsername,password=postedPassword)] 
//Pass Posted username and password to ValidateAsClient Class 
//If returns true render the view 
public ActionResult ClientLogin() 
{ 
    return View('valid') 
} 

und dann im Innern des ValidateAsClient hätte ich so etwas wie:

public class ValidateAsClient : ActionFilterAttribute 
{ 
    public string username { get; set; } 
    public string password { get; set; } 

    public Boolean ValidateAsClient() 
    { 
     return Client.validate(username,password); 
    } 
} 

Also mein Problem ist, ich weiß nicht genau, wie es funktioniert, weil ich weiß nicht, wie die Veröffentlichung von Informationen zu übergeben die [ValidateAsClient (Benutzername = PostedUsername, Passwort = PostedPassword)] und auch, wie könnte ich die Funktion ValidateAsClient funktionieren ordnungsgemäß?

Ich hoffe, das ist einfach Vielen Dank im Voraus

Antwort

7

So etwas wie diese wohl:

[AttributeUsage(AttributeTargets.All)] 
public sealed class ValidateAsClientAttribute : ActionFilterAttribute 
{ 
    private readonly NameValueCollection formData; 
    public NameValueCollection FormData{ get { return formData; } } 

    public ValidateAsClientAttribute (NameValueCollection formData) 
    { 
     this.formData = formData; 
    } 

    public override void OnActionExecuting 
       (ActionExecutingContext filterContext) 
    { 
     string username = formData["username"]; 
     if (string.IsNullOrEmpty(username)) 
     { 
      filterContext.Controller.ViewData.ModelState.AddModelError("username"); 
     } 
     // you get the idea 
    } 
} 

Und es wie folgt verwenden:

[ValidateAsClient(HttpContext.Request.Form)] 
+10

Ich denke, Sie könnten mit 'filterContext.HttpContext.Request.Form' auf die Formularsammlung zugreifen, anstatt sie zu übergeben. –

+0

vielen Dank für das HeavyWave sehr gut, eine andere Frage: Gibt es einen Unterschied zwischen ActionExecutingContext und ActionExecutedContext in diesem Fall? Danke – zanona

+0

ActionExecutedContext sollte in der OnActionExecuted-Methode verwendet werden, die nach der Aktionsmethode des Controllers ausgeführt wird. In ActionExecutedContext haben Sie also Zugriff auf einige der Ergebnisse der Ausführung. Spiel einfach mit IntelliSense herum. –

5

Sie zu verstehen, sollte die folgende Methode außer Kraft setzen.

public override void OnActionExecuting(ActionExecutingContext context) 

Und von dem Kontextobjekt, Zugriff auf Ihre Post-Daten.

+0

Überprüfen Sie ActionExecutingContext.RequestContext.HttpContext.Request.Form, und Sie sollten in der Lage sein, den Post-Wert dort zu greifen. –

1

Ich würde dieses Problem mit einem benutzerdefinierten Binder in ASP.NET MVC lösen.

Angenommen, Ihre Aktion wird die folgende Signatur haben.

public ActionResult MyAction(MyParameter param) 
{ 
    if(param.isValid) 
    return View("valid"); 
    else 
    return View("invalid"); 
} 

MyParam Klasse:

public class MyParameter 
    { 
     public string UserName{get;set;} 
     public string Password {get;set;} 

     public bool isValid 
     { 
     //check if password and username is valid. 
     } 

} 

Eine dann die kundenspezifische Mappe

public class CustomBinder:IModelBinder 
{ 
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
     { 
      var p = new MyParam(); 
      // extract necessary data from the bindingcontext like 
      p.UserName = bindingContext.ValueProvider["username"] != null 
         ? bindingContext.ValueProvider["username"].AttemptedValue 
         : ""; 
      //initialize other attributes. 
     } 
} 
+0

Dies ist ein Over-Design für eine einfache Aufgabe. @ HeavyWave bot eine hervorragende und einfache Lösung. – reflog

+0

Tss ... Ich wusste einfach nicht andere Möglichkeiten, es zu tun :). –

3

Ich denke nicht, dass es eine gute Idee ist, in diesem Fall eine ActionFilterAttribute zu verwenden. Und was Sie tun möchten, ist definitiv nicht dasselbe wie Authorize Attribut tut.

Das Attribut Authorize fügt nur eine gemeinsame Logik in eine Steuerung/Aktion ein. Welches ist:

Umleiten auf Anmeldeseite, wenn der Benutzer nicht angemeldet ist. Andernfalls lassen Sie die Aktion ausgeführt werden.

Ihre Aktion ClientLogin macht genau das, was sie gerade tun soll.
Es wäre ein schlechter Entwurf, diese Logik zu einem ActionFilterAttribute zu übertragen.

+0

Sie haben Recht, es ist keine gute Idee, etwas, das nur von einer Aktion verwendet werden sollte, in ein Attribut umzuwandeln. Authorize gibt an, dass die Aktion erfordert, dass der Benutzer autorisiert wird, und enthält keine Logik. –

+0

Ja, ich verstehe Sie zeigen, eigentlich ist das Problem, dass ich ein paar verschiedene Aktionen durch den Client in der ganzen App durchgeführt werden würde, und dies würde erfordern, dass der Client angemeldet sein, sonst würde es ihn umleiten Loginseite. So dachte ich, es könnte viel einfacher und schöner (wie ich jetzt sagen kann, da ich auf ASP.NET gestartet bin, so tut mir leid, dass etwas falsch angewendet) einen [ValidateAsClient] am Anfang jeder Methode setzen . Aber ich bin mir nicht sicher, ob das richtig ist, danke für deine Eingaben – zanona

+0

Nun, es würde nichts kaputt machen, um es auf deine Art zu machen. :) Einfach nicht ganz natürlich, das Attribut so zu verwenden. Das ist alles. –