ASP.NET MVC - ActionFilterAttribute для проверки данных POST
-
05-07-2019 - |
Вопрос
На самом деле у меня есть приложение, которое использует WebService для получения информации о некоторых клиентах. Поэтому я проверял информацию для входа в свой ActionResult, например:
[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");
}
}
Где Client.Validate () - это метод, который возвращает логическое значение на основе информации, предоставленной для имени пользователя и пароля POST
Но я передумал и хотел бы использовать этот красивый ActionFilterAttributes в начале метода, чтобы он просто отображался, если Client.validate () возвращает true, точно так же, как [Authorize], но с моим пользовательским webservice, поэтому я бы хотел что-то вроде:
[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')
}
а затем внутри ValidateAsClient у меня будет что-то вроде:
public class ValidateAsClient : ActionFilterAttribute
{
public string username { get; set; }
public string password { get; set; }
public Boolean ValidateAsClient()
{
return Client.validate(username,password);
}
}
Итак, моя проблема в том, что я не знаю точно, как заставить это работать, потому что я не знаю, как передать информацию POSTED в [ValidateAsClient (username = postsUsername, password = postsPassword)] а также как сделать так, чтобы функция ValidateAsClient работала правильно?
Надеюсь, это легко понять Заранее спасибо
Решение
Примерно так, наверное:
[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
}
}
И используйте это так:
[ValidateAsClient(HttpContext.Request.Form)]
Другие советы
Вы должны переопределить следующий метод.
public override void OnActionExecuting(ActionExecutingContext context)
А из объекта контекста получите доступ к своим данным поста.
Я не думаю, что в этом случае рекомендуется использовать ActionFilterAttribute
. И то, что вы хотите сделать, определенно не совпадает с тем, что делает атрибут Authorize
. Р>
Атрибут Authorize
просто внедряет общую логику в контроллер / действие. Который является:
Перенаправить на страницу входа, если пользователь не вошел в систему. В противном случае разрешите выполнение действия.
Ваше действие ClientLogin
делает именно то, что оно должно делать в данный момент.
Было бы плохим дизайном переносить эту логику в ActionFilterAttribute
.
Я бы решил эту проблему с помощью специального связующего в ASP.NET MVC.
Предположим, ваше действие будет иметь следующую подпись.
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.
}
}
Затем пользовательский переплет
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.
}
}