เปลี่ยนเส้นทางจากแอตทริบิวต์ตัวกรองการกระทำ


139

เป็นวิธีที่ดีที่สุดในการเปลี่ยนเส้นทางในActionFilterAttributeอะไร ฉันได้รับการActionFilterAttributeเรียกIsAuthenticatedAttributeFilterและตรวจสอบค่าของตัวแปรเซสชัน หากตัวแปรเป็นเท็จฉันต้องการให้แอปพลิเคชันเปลี่ยนเส้นทางไปยังหน้าเข้าสู่ระบบ ฉันต้องการเปลี่ยนเส้นทางโดยใช้ชื่อเส้นทางSystemLoginอย่างไรก็ตามวิธีการเปลี่ยนเส้นทางใด ๆ ณ จุดนี้จะใช้ได้


คำตอบ:


187

ตั้งค่า filterContext.Result

ด้วยชื่อเส้นทาง:

filterContext.Result = new RedirectToRouteResult("SystemLogin", routeValues);

คุณสามารถทำสิ่งที่ชอบ:

filterContext.Result = new ViewResult
{
    ViewName = SharedViews.SessionLost,
    ViewData = filterContext.Controller.ViewData
};

หากคุณต้องการใช้RedirectToAction:

คุณสามารถทำให้ประชาชนRedirectToActionวิธีการในการควบคุมของคุณ ( โดยเฉพาะอย่างยิ่งในการควบคุมฐาน ) ที่เพียงสายการคุ้มครองจากRedirectToAction System.Web.Mvc.Controllerการเพิ่มวิธีนี้จะทำให้การโทรสาธารณะของคุณ RedirectToActionจากตัวกรอง

public new RedirectToRouteResult RedirectToAction(string action, string controller)
{
    return base.RedirectToAction(action, controller);
}

จากนั้นตัวกรองของคุณจะมีลักษณะดังนี้:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var controller = (SomeControllerBase) filterContext.Controller;
    filterContext.Result = controller.RedirectToAction("index", "home");
}

8
ใช้งานได้ แต่ไม่ควรมีวิธี RedirectToAction หรือไม่
Ben Mills

@BenMills มีอย่างไรก็ตามprotectedคุณจะไม่สามารถเข้าถึงได้จากตัวกรอง
James

10
คำถามของฉันคือตอนนี้ทำไม Microsoft ตัดสินใจที่จะทำให้ตัวกรองนี้protectedต้องมีคำอธิบายที่สมเหตุสมผลหรือไม่ ฉันรู้สึกสกปรกมากที่นิยามใหม่การเข้าถึงนี้RedirectToActionโดยไม่เข้าใจว่าทำไมมันจึงถูกห่อหุ้มตั้งแต่แรก
Matthew Marlin

2
@MatthewMarlin - ดูคำตอบโดย Syakur สำหรับคำตอบที่ถูกต้องสำหรับการเปลี่ยนเส้นทางไปยังการดำเนินการ คุณถูกต้องที่คุณไม่ควรเรียกตัวควบคุมโดยตรงจากตัวกรองการกระทำนั่นคือคำจำกัดความของการมีเพศสัมพันธ์อย่างแน่นหนา
NightOwl888

1
@Akbari คุณลองตั้งค่าคุณสมบัติการสั่งซื้อของแอตทริบิวต์แล้วหรือยัง FilterScope ยังจะส่งผลกระทบต่อคำสั่งการดำเนินการ
CRice

79

อีกวิธีหนึ่งคือการเปลี่ยนเส้นทางหากกำลังเรียกรหัสของคุณเองคุณสามารถใช้สิ่งนี้:

actionContext.Result = new RedirectToRouteResult(
    new RouteValueDictionary(new { controller = "Home", action = "Error" })
);

actionContext.Result.ExecuteResult(actionContext.Controller.ControllerContext);

มันไม่ใช่การเปลี่ยนเส้นทางที่บริสุทธิ์ แต่ให้ผลลัพธ์ที่คล้ายกันโดยไม่มีค่าใช้จ่ายที่ไม่จำเป็น


คุณช่วยฉัน ขอบคุณ!
Edgar Salazar

25
ทราบว่าคุณไม่ควรได้รับการเรียกร้องactionContext.Result.ExecuteResultจากภายในตัวกรองการกระทำของคุณ - MVC จะทำโดยอัตโนมัติหลังจากที่ตัวกรองการกระทำวิ่ง (ให้actionContext.Resultเป็นไม่เป็นโมฆะ)
NightOwl888

12

ฉันใช้ MVC4 ฉันใช้วิธีการต่อไปนี้เพื่อเปลี่ยนเส้นทางหน้าจอ html แบบกำหนดเองเมื่อมีการละเมิดสิทธิ์

ขยายAuthorizeAttributeคำพูดCutomAuthorizer แทนที่OnAuthorizationและHandleUnauthorizedRequest

การลงทะเบียนในCustomAuthorizerRegisterGlobalFilters

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{

    filters.Add(new CustomAuthorizer());
}

เมื่อระบุการunAuthorizedเรียกการเข้าถึงHandleUnauthorizedRequestและเปลี่ยนเส้นทางไปยังการดำเนินการควบคุมที่เกี่ยวข้องดังแสดงด้านล่าง


public class CustomAuthorizer : AuthorizeAttribute
{

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        bool isAuthorized = IsAuthorized(filterContext); // check authorization
        base.OnAuthorization(filterContext);
        if (!isAuthorized && !filterContext.ActionDescriptor.ActionName.Equals("Unauthorized", StringComparison.InvariantCultureIgnoreCase)
            && !filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.Equals("LogOn", StringComparison.InvariantCultureIgnoreCase))
        {

            HandleUnauthorizedRequest(filterContext);

        }
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.Result =
       new RedirectToRouteResult(
           new RouteValueDictionary{{ "controller", "LogOn" },
                                          { "action", "Unauthorized" }

                                         });

    }
}

9

ดูเหมือนว่าคุณต้องการนำมาใช้ใหม่หรือขยายออกAuthorizeAttributeไป ถ้าเป็นเช่นนั้นคุณควรตรวจสอบให้แน่ใจว่าคุณได้รับสิ่งนั้นไม่ใช่ActionFilterAttributeเพื่อให้ ASP.NET MVC ทำงานให้คุณได้มากขึ้น

นอกจากนี้คุณต้องการตรวจสอบให้แน่ใจว่าคุณอนุญาตก่อนที่จะทำงานจริงใด ๆ ในวิธีการดำเนินการ - มิฉะนั้นความแตกต่างเพียงอย่างเดียวระหว่างการล็อกอินและจะไม่เป็นหน้าที่คุณเห็นเมื่อทำงานเสร็จ

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        // Do whatever checking you need here

        // If you want the base check as well (against users/roles) call
        base.OnAuthorization(filterContext);
    }
}

มีคำถามที่ดีพร้อมคำตอบพร้อมรายละเอียดเพิ่มเติมเกี่ยวกับ SO


5

ลองตัวอย่างต่อไปนี้ควรมีความชัดเจนมาก:

public class AuthorizeActionFilterAttribute : ActionFilterAttribute
{
  public override void OnActionExecuting(FilterExecutingContext filterContext)
  {
    HttpSessionStateBase session = filterContext.HttpContext.Session;
    Controller controller = filterContext.Controller as Controller;

    if (controller != null)
    {
      if (session["Login"] == null)
      {
        filterContext.Cancel = true;
        controller.HttpContext.Response.Redirect("./Login");
      }
    }

    base.OnActionExecuting(filterContext);
  }
}

สิ่งนี้ใช้งานได้สำหรับฉันฉันต้องตรวจสอบค่าสตริงข้อความค้นหาหากผู้ใช้พยายามเปลี่ยนค่าสตริงข้อความค้นหาและพยายามเข้าถึงข้อมูลที่ไม่ได้รับอนุญาตจากเขา / เธอมากกว่าที่ฉันเปลี่ยนเส้นทางไปยังหน้าข้อความที่ไม่ได้รับอนุญาตโดยใช้ ActionFilterAttribute
Sameer

3

นี่คือโซลูชันที่คำนึงถึงหากคุณใช้คำขอ Ajax

using System;
using System.Web.Mvc;
using System.Web.Routing;

namespace YourNamespace{        
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AuthorizeCustom : ActionFilterAttribute {
        public override void OnActionExecuting(ActionExecutingContext context) {
            if (YourAuthorizationCheckGoesHere) {               
                string area = "";// leave empty if not using area's
                string controller = "ControllerName";
                string action = "ActionName";
                var urlHelper = new UrlHelper(context.RequestContext);                  
                if (context.HttpContext.Request.IsAjaxRequest()){ // Check if Ajax
                    if(area == string.Empty)
                        context.HttpContext.Response.Write($"<script>window.location.reload('{urlHelper.Content(System.IO.Path.Combine(controller, action))}');</script>");
                    else
                        context.HttpContext.Response.Write($"<script>window.location.reload('{urlHelper.Content(System.IO.Path.Combine(area, controller, action))}');</script>");
                } else   // Non Ajax Request                      
                    context.Result = new RedirectToRouteResult(new RouteValueDictionary( new{ area, controller, action }));             
            }
            base.OnActionExecuting(context);
        }
    }
}

1

สิ่งนี้ใช้ได้สำหรับฉัน (asp.net core 2.1)

using JustRide.Web.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace MyProject.Web.Filters
{
    public class IsAuthenticatedAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (context.HttpContext.User.Identity.IsAuthenticated)
                context.Result = new RedirectToActionResult(nameof(AccountController.Index), "Account", null);
        }
    }
}



[AllowAnonymous, IsAuthenticated]
public IActionResult Index()
{
    return View();
}

0

คุณสามารถสืบทอดตัวควบคุมของคุณจากนั้นใช้ภายในตัวกรองการกระทำ

ภายในคลาส ActionFilterAttribute ของคุณ:

   if( filterContext.Controller is MyController )
      if(filterContext.HttpContext.Session["login"] == null)
           (filterContext.Controller as MyController).RedirectToAction("Login");

ภายในตัวควบคุมฐานของคุณ:

public class MyController : Controller 
{
    public void  RedirectToAction(string actionName) { 
        base.RedirectToAction(actionName); 
    }
}

จุดด้อย สิ่งนี้เป็นการเปลี่ยนแปลงตัวควบคุมทั้งหมดเพื่อสืบทอดจากคลาส "MyController"

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.