2009-10-21 47 views
5

Actualmente tengo una aplicación que está utilizando un servicio web para recuperar información de algunos clientes. Así que fue la validación de la información de acceso dentro de mi ActionResult como:ASP.NET MVC - ActionFilterAttribute para validar datos 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"); 
    } 
} 

Dónde Client.Validate() es un método que devuelve un valor lógico basado en la información proporcionada en el nombre de usuario y contraseña de POST

Pero Cambié de opinión y me gustaría utilizar ese bonito ActionFilterAttributes al comienzo del método, de modo que solo se representará si Client.validate() devuelve true, igual que [Authorize] pero con mi servicio web personalizado, así que lo haría tiene algo como:

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

y luego dentro de la ValidateAsClient Me gustaría tener algo como:

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

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

Así que mi problema es que no sé exactamente cómo hacer que funcione, porque no sé cómo pasar la información publicada en el [ValidateAsClient (username = postedUsername, password = postingPassword)] y también, ¿cómo podría hacer que la función ValidateAsClient funcione correctamente?

espero que esto es fácil de entender Gracias de antemano

Respuesta

7

Algo como esto probablemente:

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

Y utilizar de esta manera:

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

Creo que podría acceder a la colección de formularios con 'filterContext.HttpContext.Request.Form', en lugar de pasarlo. –

+0

gracias por ese HeavyWave muy bueno, otra pregunta: ¿Hay alguna diferencia entre el uso de ActionExecutingContext y ActionExecutedContext en este caso? Gracias – zanona

+0

Se supone que ActionExecutedContext se usa en el método OnActionExecuted, que se ejecuta después del método de acción del controlador. Entonces, en ActionExecutedContext tiene acceso a algunos de los resultados de la ejecución. Solo juegue con IntelliSense. –

5

debe reemplazar el método siguiente.

public override void OnActionExecuting(ActionExecutingContext context) 

Y desde el objeto de contexto, acceda a los datos de su publicación.

+0

Compruebe ActionExecutingContext.RequestContext.HttpContext.Request.Form, y debería ser capaz de tomar el valor de la publicación allí. –

1

Resolvería este problema con una carpeta personalizada en ASP.NET MVC.

Supongamos que su acción tendrá la siguiente firma. clase

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 entonces la carpeta de encargo

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

esto es un diseño de más para una tarea simple. @HeavyWave proporcionó una solución excelente y simple. – reflog

+0

Tss ... Yo simple no sabía otras formas de hacerlo :). –

3

No creo que sea una buena idea usar un ActionFilterAttribute en este caso. Y lo que quiere hacer definitivamente no es lo mismo que hace el atributo Authorize.

El atributo Authorize simplemente inyecta una lógica común en un controlador/acción. Que es:

Redirecciona a la página de inicio de sesión, si el usuario no inicia sesión. De lo contrario, deja que se ejecute la acción.

Su acción ClientLogin hace justo lo que se supone que debe hacer en este momento.
Sería un mal diseño llevar esa lógica a un ActionFilterAttribute.

+0

Tiene razón, no es una buena idea convertir algo que solo debería ser utilizado por una Acción en un atributo. Autorizar indica que la Acción requiere que el usuario esté autorizado, no contiene ninguna lógica. –

+0

Sí, entiendo que el problema es que el cliente debería realizar un par de acciones diferentes en toda la aplicación, y esto requeriría que el cliente estuviera conectado, de lo contrario, se lo redirigiría a un página de inicio de sesión. Así que estaba pensando que podría ser mucho más fácil y hermoso (como puedo decir por ahora, ya que soy un iniciado en ASP.NET, lo siento por cualquier error aplicado) para poner un [ValidateAsClient] al comienzo de cada método . Pero no estoy seguro si esto es correcto, gracias por sus entradas – zanona

+0

Bueno, no rompería nada para hacerlo a su manera. :) Simplemente no es totalmente natural usar el atributo de esa manera. Eso es todo. –

Cuestiones relacionadas