2009-10-21 11 views
5

In realtà, ho un'applicazione che utilizza un servizio Web per recuperare alcune informazioni sui client. così mi è stato la convalida dei dati dati dentro la mia ActionResult come:ASP.NET MVC - ActionFilterAttribute per convalidare i dati POST

[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"); 
    } 
} 

Dove Client.Validate() è un metodo che restituisce un valore booleano in base alle informazioni fornite sul nome utente e la password POST

Ma io ho cambiato idea e vorrei usare quel simpatico ActionFilterAttributes all'inizio del metodo in modo tale che venga reso solo se il client.validate() restituisce true, proprio come [Authorize] ma con il mio webservice personalizzato, quindi vorrei avere qualcosa come:

[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') 
} 

e poi dentro la ValidateAsClient vorrei avere qualcosa di simile:

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

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

Quindi il mio problema è, non so esattamente come farlo funzionare, perché non so come passare le informazioni pubblicate a the [ValidateAsClient (username = postatoUsername, password = postatoPassword)] e inoltre, come è possibile che la funzione ValidateAsClient funzioni correttamente?

Spero che questo sia facile da capire Grazie in anticipo

risposta

7

Qualcosa di simile probabilmente:

[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 
    } 
} 

e usarlo in questo modo:

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

Penso che potresti accedere alla raccolta moduli con 'filterContext.HttpContext.Request.Form', invece di passarlo sopra. –

+0

grazie per l'ottimo HeavyWave, un'altra domanda: c'è qualche differenza tra l'uso di ActionExecutingContext e ActionExecutedContext in questo caso? Grazie – zanona

+0

ActionExecutedContext deve essere utilizzato nel metodo OnActionExecuted, che viene eseguito dopo il metodo di azione del controllore. Quindi in ActionExecutedContext hai accesso ad alcuni dei risultati dell'esecuzione. Basta giocarci con IntelliSense. –

5

Si dovrebbe eseguire l'override del metodo seguente.

public override void OnActionExecuting(ActionExecutingContext context) 

E dall'oggetto contesto, accedere ai dati del post.

+0

Controlla ActionExecutingContext.RequestContext.HttpContext.Request.Form e dovresti essere in grado di afferrare il valore del post lì. –

1

Vorrei risolvere questo problema con un raccoglitore personalizzato in ASP.NET MVC.

Supponiamo che la tua azione abbia la seguente firma. Classe

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

MyParam:

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

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

} 

Un quindi il legante personalizzato

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

questo è un over design per un compito semplice. @HeavyWave ha fornito una soluzione eccellente e semplice. – reflog

+0

Tss ... Semplicemente non conoscevo altri modi per farlo :). –

3

In questo caso non credo sia una buona idea utilizzare uno ActionFilterAttribute. E quello che vuoi fare non è sicuramente lo stesso che fa l'attributo Authorize.

L'attributo Authorize immette solo una logica comune in un controller/azione. Quale è:

Reindirizzare alla pagina di accesso, se l'utente non è connesso. Altrimenti lasciare eseguire l'azione.

L'azione ClientLogin fa esattamente ciò che deve fare al momento.
Sarebbe un cattivo progetto portare questa logica su un ActionFilterAttribute.

+0

Hai ragione, non è una buona idea girare qualcosa che dovrebbe essere usato solo da un'azione in un attributo. Autorizza indica che l'Azione richiede che l'utente sia autorizzato, che non contenga alcuna logica. –

+0

Sì, ho capito, il problema è che avrei dovuto eseguire un paio di azioni diverse da parte del client su tutta l'app, e questo richiederebbe il login al client altrimenti lo reindirizzerebbe a un altro pagina di login. Quindi stavo pensando che potrebbe essere molto più semplice e bello (come posso dire per ora visto che sono avviato su ASP.NET, mi dispiace per tutto ciò che è sbagliato applicato) per mettere un [ValidateAsClient] all'inizio di ogni metodo . Ma non sono sicuro che sia corretto, grazie per i tuoi input – zanona

+0

Beh, non si romperà nulla per farlo a modo tuo. :) Semplicemente non del tutto naturale usare l'attributo in questo modo. È tutto. –