จะเพิ่มฟิลเตอร์ Global ASP.Net Web Api ได้อย่างไร?


98

ฉันได้สร้างตัวกรอง Web Api (โดยใช้System.Web.Http.Filters.ActionFilterAttribute) แต่ฉันไม่สามารถทำให้มันใช้งานได้ภายใน ASP.Net MVC 4 ฉันพยายามเพิ่มมันลงในRegisterGlobalFilters()วิธีการ แต่ไม่ได้ผล

ดังนั้นหากใครใช้ Web Api ที่โฮสต์ใน ASP.Net MVC หนึ่งจะลงทะเบียนตัวกรองได้อย่างไร

คำตอบ:


110

รหัสต่อไปนี้ใน Global.asax ของฉันใช้ได้กับฉัน:

public static void RegisterWebApiFilters(System.Web.Http.Filters.HttpFilterCollection filters)
{
  filters.Add(new MyWebApiFilter());
}

protected void Application_Start()
{
  RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}

6
ใครช่วยอธิบายว่าเกิดอะไรขึ้นที่นี่? เหตุใดจึงมีตัวกรองส่วนกลางสองชุด นั่นไม่ทำให้ 'Global' เป็น oxymoron หรือไม่?
Luke Puplett

6
ตัวกรองชุดหนึ่งมีไว้สำหรับ MVC และอีกชุดหนึ่งสำหรับ Web API พวกเขาเป็นสองสิ่งที่แยกจากกันและโดยปกติคุณไม่ต้องการให้ตัวกรองหนึ่งถูกนำไปใช้กับอีกสิ่งหนึ่ง
Shane Courtrille

2
ตัวกรอง WebApi ของฉันถูกเรียกสองครั้ง ใครมีปัญหานี้?
Andrew Kalashnikov

87

โปรดทราบว่าคำตอบนี้เป็นจริงถึง MVC 5 / Web API 2

คำตอบสั้น ๆ :ตัวกรอง MVC และ Web API ไม่สามารถใช้งานร่วมกันได้และหากคุณต้องการลงทะเบียนทั่วโลกคุณต้องใช้คลาสการกำหนดค่าที่เหมาะสมสำหรับแต่ละรายการ

คำตอบแบบยาว: ASP.NET MVC และ Web API ได้รับการออกแบบมาโดยเฉพาะเพื่อให้ทำงานในลักษณะเดียวกัน แต่แท้จริงแล้วเป็นสิ่งมีชีวิตที่แตกต่างกัน

Web API อยู่ภายใต้System.Web.Httpเนมสเปซในขณะที่ MVC อยู่ภายใต้System.Web.Mvcเนมสเปซ ทั้งสองจะอยู่เคียงข้างกันอย่างมีความสุข แต่ไม่มีอีกคนหนึ่งและแม้จะมีความคล้ายคลึงกันในรูปแบบการเขียนโปรแกรมการใช้งานพื้นฐานก็แตกต่างกัน เช่นเดียวกับตัวควบคุม MVC และตัวควบคุม Web API จะสืบทอดคลาสคอนโทรลเลอร์พื้นฐานที่แตกต่างกัน (MVC มีชื่อเรียกง่ายๆControllerและชื่อของWeb API ApiController) ตัวกรอง MVC และตัวกรอง Web API สืบทอดมาจากFilterAttributeคลาสที่แตกต่างกัน(ทั้งสองใช้ชื่อเดียวกันในกรณีนี้ แต่เป็นคลาสแยกกันที่มีชีวิตอยู่ ในเนมสเปซตามลำดับ)

ตัวกรองส่วนกลางของ Web API จะลงทะเบียนผ่านHttpConfigurationอ็อบเจ็กต์ที่มีให้คุณในRegisterเมธอด WebApiConfig.cs หากคุณใช้เทมเพลตโปรเจ็กต์กับ WebActivator:

public static void Register(HttpConfiguration config)
{
    //stuff before
    config.Filters.Add(new MyWebApiFilter());
    //stuff after
}

หรืออย่างอื่นใน global.asax.cs:

GlobalConfiguration.Configuration.Filters.Add(new MyWebApiFilter());

ตัวกรองส่วนกลาง Mvc ได้รับการลงทะเบียนโดยใช้GlobalFilterCollectionอ็อบเจ็กต์ซึ่งพร้อมใช้งานสำหรับคุณผ่านRegisterGlobalFiltersวิธีการ FilterConfig.cs สำหรับโปรเจ็กต์ที่ใช้ WebActivator:

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        //stuff before
        filters.Add(new MyMvcFilter());
        //stuff after
    }
}

หรือในไฟล์ global.asax.cs โดยวิธีการGlobalFilters.Filtersรวบรวมสำหรับผู้ที่ไม่มี WebActivator:

GlobalFilters.Filters.Add(new MyMvcFilter());

เป็นที่น่าสังเกตว่าในทั้งสองกรณีคุณไม่จำเป็นต้องสืบทอดจากFilterAttributeประเภทที่เหมาะสม ตัวกรอง Web API จำเป็นต้องใช้อินเทอร์เฟซ System.Web.Http.IFilter เท่านั้นในขณะที่การลงทะเบียนตัวกรอง MVC จะตรวจสอบเพื่อให้แน่ใจว่าคลาสของคุณสืบทอดอินเทอร์เฟซตัวกรองจำนวนหนึ่งที่กำหนดไว้ในSystem.Web.Mvcเนมสเปซ


การเพิ่มตัวกรอง Web Api ที่กำหนดเองใน webapiconfig.cs ใช้ได้ผลกับฉัน ฉันไม่เข้าใจว่าทำไมมันถึงไม่ได้ผลเมื่อเพิ่มใน global.asax.cs
Tatipaka

ขอบคุณ @tatipaka. การเพิ่มลงใน webapiconfig ใช้งานได้
Gokulnath

12

สำหรับ MVC 4 RC ชื่อคลาสที่ถูกต้องคือHttpFilterCollection :

public static void RegisterWebApiFilters(System.Web.Http.Filters.HttpFilterCollection filters)
{
    filters.Add(new MyWebApiFilter());
}

protected void Application_Start()
{
    RegisterWebApiFilters(GlobalConfiguration.Configuration.Filters);
}

8

แทนที่จะใช้ตัวกรองส่วนกลางฉันชอบทำสิ่งนี้:

[MyWebApiFilter]
public class CustomizedApiControllerBase : ApiController
{
   ...
}

และหลังจากนั้นสืบทอดตัวควบคุม api ทั้งหมดจากCustomizedApiControllerBase วิธีนี้จะแสดงออกได้ชัดเจนกว่าเมื่อเปรียบเทียบกับตัวกรองส่วนกลางในไฟล์ global.ascx


ฉันสร้างตัวกรองที่สืบทอดมาจาก System.Web.Http.Filters.ActionFilterAttribute และดำเนินการใช้งานโดยตรงกับวิธีการที่ฉันต้องการ มันใช้งานได้จริงทำไมฉันไม่จำเป็นต้องลงทะเบียน?
joedotnot

@joedotnot เป็นเรื่องเกี่ยวกับตัวกรอง "global" ไม่ใช่ตัวกรองที่เฉพาะเจาะจง หากคุณสามารถระบุวิธีการที่คุณต้องการกรองได้แนวทางของคุณก็ใช้ได้ แต่เมื่อคุณต้องการกรองโดยไม่คำนึงถึงการดำเนินการของคอนโทรลเลอร์คุณต้องมีตัวกรองส่วนกลาง
Mahmoud Moravej
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.