如何在ReactJS中无哈希使用路由、兼容ASP.NET MVC页面刷新及移除URL哈希?
Hey there! Let's tackle both of your questions step by step—they're closely linked, so we'll cover removing the hash first, then make sure ASP.NET MVC handles page refreshes correctly.
To get rid of the # in your URLs, you just need to swap out HashRouter with BrowserRouter from react-router-dom:
- First, update your import statement:
// Before (with hash routing) import { HashRouter as Router, Route, Switch } from 'react-router-dom'; // After (clean, hash-free routing) import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; - Then use
BrowserRouterexactly like you did withHashRouter:function App() { return ( <Router> <Switch> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> {/* Add all your other client-side routes here */} </Switch> </Router> ); }
That's the React side sorted—but if you refresh the page now in ASP.NET MVC, you'll hit a 404 error. Let's fix that next.
The issue here is that when you refresh a page like /about, ASP.NET MVC tries to find a server-side route matching that URL—which doesn't exist, since those routes are handled client-side by React Router. We need to tell MVC to redirect all non-api/non-static requests to your React entry page (usually Index.cshtml).
Step 1: Update RouteConfig.cs
Open App_Start/RouteConfig.cs and add a catch-all route at the end of your route definitions (so it only catches URLs that don't match existing server routes):
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // Keep your existing MVC routes here (if you have any) routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); // Add this catch-all route to send all unmatched URLs to React's entry page routes.MapRoute( name: "ReactCatchAll", url: "{*url}", defaults: new { controller = "Home", action = "Index" } ); } }
This tells MVC that any URL that doesn't match a server-side route should load the Home/Index action, which serves your React app.
Step 2: Protect static assets
Ensure static files (like CSS, JS bundles, images) aren't caught by the catch-all route. IIS typically handles static files before routing kicks in, but if you run into issues, add explicit ignore rules:
// Add these above your other routes routes.IgnoreRoute("Content/{*pathInfo}"); routes.IgnoreRoute("Scripts/{*pathInfo}"); routes.IgnoreRoute("dist/{*pathInfo}"); // If your React bundle is in a dist folder
Step 3: Verify your React entry page
Make sure your Index.cshtml is set up to render the React app correctly, regardless of the URL. The root div should be present, and your bundled React code should target it:
<div id="root"></div> <script src="~/dist/bundle.js"></script> <!-- Path to your bundled React code -->
Bonus: Separate API routes (if applicable)
If you have ASP.NET Web API routes, make sure they're registered before MVC routes so they don't get caught by the catch-all. In WebApiConfig.cs:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { // Register API routes first config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
And in Global.asax.cs, call WebApiConfig.Register before RouteConfig.Register:
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); // API first FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); // MVC routes after BundleConfig.RegisterBundles(BundleTable.Bundles); }
That's it! Now your React app will use clean, hash-free URLs, and refreshing any page will load correctly through ASP.NET MVC.
内容的提问来源于stack exchange,提问作者Mohammad Javad Abbasian

