Web API Razor视图路由最佳处理方式咨询:现有实现是否规范?
Hey there! Great question—let’s unpack this for you.
First off: your current approach (using API controllers for data fetching and regular controllers for view navigation/ActionResult returns) is totally valid and aligns with the principle of separation of concerns. It’s a common pattern in ASP.NET (Core) projects, especially when you’re mixing server-rendered views (like Razor Pages or MVC views) with API endpoints for things like AJAX calls or mobile app integration.
That said, there are ways to refine this setup depending on your project’s scale and needs:
1. Lean into Controller vs. ControllerBase (for ASP.NET Core)
If you’re working with ASP.NET Core, make sure you’re using the right base class:
- API controllers should inherit from
ControllerBase—this is a lightweight base class that excludes view-related features (likeView()orViewBag), keeping your API-focused code clean. - Regular view controllers inherit from
Controller, which includes all the view-rendering and navigation tools you need.
This small tweak makes your code’s intent clearer and avoids unnecessary overhead in API controllers.
2. Consider Your Project Architecture
- Server-Rendered (SSR) Apps: If you’re building a traditional app where most pages are rendered server-side, your current setup is ideal. Regular controllers handle page navigation and view rendering, while API controllers power dynamic parts of the UI (like filtering data without reloading the page).
- Full Frontend-Backend Separation: If you plan to use a frontend framework (React, Vue, Angular) where the frontend handles routing and view rendering, you can ditch regular controllers entirely. Your backend will only expose API endpoints, and all navigation happens via frontend routing. This is great for larger, more dynamic apps but requires a separate frontend codebase.
3. Avoid Duplication with Service Layers
The biggest optimization you can make, regardless of your architecture, is to extract shared business logic into a service layer. For example, if both your API controller and regular controller need to fetch product data, don’t write the database call twice. Instead:
- Create an interface like
IProductServicewith methods likeGetAllProductsAsync(). - Implement this service with your database logic.
- Inject the service into both your API and regular controllers.
Here’s a quick example of how this looks:
API Controller
[ApiController] [Route("api/products")] public class ProductsApiController : ControllerBase { private readonly IProductService _productService; public ProductsApiController(IProductService productService) { _productService = productService; } [HttpGet] public async Task<IActionResult> GetAll() { var products = await _productService.GetAllProductsAsync(); return Ok(products); } }
Regular View Controller
public class ProductsController : Controller { private readonly IProductService _productService; public ProductsController(IProductService productService) { _productService = productService; } public async Task<IActionResult> Index() { var products = await _productService.GetAllProductsAsync(); return View(products); } }
Final Verdict
Your initial approach isn’t just "okay"—it’s a solid starting point. Whether it’s "optimal" depends on your end goals:
- Stick with it if you’re building a server-rendered app with some dynamic API-powered features.
- Shift to a pure API backend if you’re going full frontend-framework.
- Always extract shared logic to a service layer to keep your code DRY and maintainable.
内容的提问来源于stack exchange,提问作者user3442776

