Custom route that match a single specific url - asp.net-mvc

In my mvc app, I want to dynamically generate a specific url :
https://myapp.corp.com/.well-known/microsoft-identity-association.json
This endpoint should produce a small file based on values in the web.config file. So I created this controller :
public class HostingController : Controller
{
// GET: Hosting
[OutputCache(Duration = 100, VaryByParam = "none")]
public ActionResult MicrosoftIdentityAssociation() => Json(new
{
associatedApplications = new[]
{
new { applicationId = WebConfigurationManager.AppSettings.Get("ClientId") }
}
});
}
And I changed the routing configuration like this :
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Azure domain registration",
".well-known/microsoft-identity-association.json",
new { controller = "Hosting", action= "MicrosoftIdentityAssociation" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
I expect the url to produce json like :
{
"associatedApplications": [
{
"applicationId": "1562019d-44f7-4a9d-9833-64333f52181d"
}
]
}
But when I target the url, I got a 404 error.
What's wrong ? how to fix ?

You can use a route attribute:
[Route("~/.well-known/microsoft-identity-association.json")]
[OutputCache(Duration = 100, VaryByParam = "none")]
public ActionResult MicrosoftIdentityAssociation()
{
..... your code
}
It was tested in postman.

Asp.Net MVC can't create route that have extension. I had to edit my Web.config to plug the MVC framework on this very specific file.
Specifically :
<system.webServer>
<handlers>
<add name="Azure domain verifier"
path=".well-known/microsoft-identity-association.json"
verb="GET" type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0"
/>
</handlers>
</system.webServer>
From this point, I was able to route to my custom controller action using either routeconfig.cs file or the [RouteAttribute]

Related

RouteConfig and filename with extension - MVC5

I have the following URLs:
/Meetings/doc1.pdf
/Meetings/doc2.pdf
I tried to set up the following in my RoouteConfig
var route = routes.MapRoute(
name: "RedirectMeetingDocs",
url: "Meetings/{filename}",
defaults: new { action= "GetAttachmentByName", controller = "Generic" },
constraints: new { filename = #"(.*?)\.(pdf|ppt)" }
);
With the following function:
[HttpGet]
public ActionResult GetAttachmentByName(string fileName)
{
...
}
However, it nevers work and I keep getting a 404 error.
I also tried:
var route = routes.MapRoute(
name: "RedirectMeetingDocs",
url: "Meetings/{filename}.{extension}",
defaults: new { action= "GetAttachmentByName", controller = "Generic" },
constraints: new { filename = new AlphaRouteConstraint(), extension = new AlphaRouteConstraint() }
);
with
public ActionResult GetAttachmentByName(string fileName, string extension)
{
But nothing works.
Any advices?
Ok I solve it by adding the following in my Web.config:
<add name="IATTCRedirectOldMeetingFiles" path="meetings/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
Now, both RouteConfig shown above work.

How do I setup default routes that match just parameters?

This is how I want my routes to work:
http://example.com -> UpdatesController.Query()
http://example.com/myapp/1.0.0.0 -> UpdatesController.Fetch("myapp", "1.0.0.0")
http://example.com/myapp/1.0.0.1 -> UpdatesController.Fetch("myapp", "1.0.0.1")
http://example.com/other/2.0.0.0 -> UpdatesController.Fetch("other", "2.0.0.0")
My controller looks like this:
public class UpdatesController : Controller {
public ActionResult Query() { ... }
public ActionResult Fetch(string name, string version) { ... }
}
The route config that I've tried is this:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Fetch",
url: "{name}/{version}",
defaults: new { controller = "Updates", action = "Fetch" },
constraints: new { name = #"^.+$", version = #"^\d+(?:\.\d+){1,3}$" }
);
routes.MapRoute(
name: "Query",
url: "",
defaults: new { controller = "Updates", action = "Query" }
);
But only the first example works. The others that should call the Fetch action method all fail with 404.
What am I doing wrong?
(I've also tried it without the route constraints, but there is no difference)
add following code to web.config, because your url contains dot value (1.0.0.0)
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
Another way
you can do it via Attribute routing.
to enable attribute routing, write below code in RouteConfig.cs
routes.MapMvcAttributeRoutes();
In controller your Action look like this
[Route("")]
public ActionResult Query()
{
return View();
}
[Route("{name}/{version}")]
public ActionResult Fetch(string name, string version)
{
return View();
}

Creating multilingual not found page in MVC

We have a multilingual website that has content in four languages.Every language is understood by the language name that we add at the first of our url.
This is our routeConfig.cs:
routes.MapRoute(
name: "Default",
url: "{lang}/{controller}/{action}/{id}/{title}",
defaults: new { lang = "fa", controller = "Home", action = "Index", id = UrlParameter.Optional,title = UrlParameter.Optional }
and this is generated the url: /en/ContactUs/Index
Also, in our controllers we get the language name from url and change the currentCulture and currentUiCulture based on it.
Now, we want to have a not found page in all of the languages. Normally, to make it happen we add an error contoller and a NotFound action and view, then we add this section in our web.config:
<customErrors mode="On" defaultRedirect="error">
<error statusCode="404" redirect="error/notfound" />
<error statusCode="403" redirect="error/forbidden" />
</customErrors>
We have added a NotFound page that we use .resx files in it to make rtl/ltr and to show the messages in four languages.
But the problem here is that in a multilingual website we are not allowed to use this address "error/notfound" because there is no languagename in it and we don't know how to add the language name in redirect="error/notfound" in the web.config file to create something like "en/error/notfound" or "fa/error/notfound".
every help would be highly appreciated
First of all, have a look at this answer for info about localizing your site via URL.
Next, <customErrors> is a catch-all for ASP.NET error messages. But in general, you have control over a 404 (routing miss) within ASP.NET MVC by using a catch-all route. In this case, you can simply localize the catch-all route and get rid of this configuration in web.config.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Localized-Default",
url: "{lang}/{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { lang = new CultureConstraint(defaultCulture: "fa", pattern: "[a-z]{2}") }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { lang = "fa", controller = "Home", action = "Index", id = UrlParameter.Optional }
);
// Catch-all route (for routing misses)
routes.MapRoute(
name: "Localized-404",
url: "{lang}/{*url}",
defaults: new { controller = "Error", action = "PageNotFound" },
constraints: new { lang = new CultureConstraint(defaultCulture: "fa", pattern: "[a-z]{2}") }
);
routes.MapRoute(
name: "Default-404",
url: "{*url}",
defaults: new { lang = "fa", controller = "Error", action = "PageNotFound" }
);
}
}
ErrorController
public class ErrorController : Controller
{
public ActionResult PageNotFound()
{
Response.CacheControl = "no-cache";
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View();
}
}
That takes care of the route misses within ASP.NET. For those that don't hit ASP.NET (assuming you are hosting using IIS), you should use the <httpErrors> section of web.config rather than <customErrors>. <httpErrors> is localizable via the prefixLanguageFilePath setting.
Optional string attribute.
Specifies the initial path segment when generating the path for a custom error. This segment appears before the language-specific portion of the custom error path. For example, in the path C:\Inetpub\Custerr\en-us\404.htm, C:\Inetpub\Custerr is the prefixLanguageFilePath.
<configuration>
<system.webServer>
<httpErrors errorMode="DetailedLocalOnly" defaultResponseMode="File" >
<remove statusCode="404" />
<error statusCode="404"
prefixLanguageFilePath="C:\Contoso\Content\errors"
path="404.htm" />
</httpErrors>
</system.webServer>
</configuration>
Which means you would need to set up a file structure with language prefix, and use static files as targets.
C:\Contoso\Content\errors\fa\404.htm
C:\Contoso\Content\errors\en\404.htm
AFAIK, this unfortunately means you need to have physical files at these locations. However, you could have the content of these pages setup to do both a meta-refresh redirect and a JavaScript redirect to the correct controller action.
<html>
<head>
<title>404 Not Found</title>
<meta http-equiv="refresh" content="1;http://www.example.com/fa/Error/PageNotFound" />
</head>
<body>
<!-- Add localized message (for those browsers that don't redirect). -->
<script>
//<!--
setTimeout(function () {
window.location = "http://www.example.com/fa/Error/PageNotFound";
}, 1000);
//-->
</script>
</body>
</html>
The customErrors section in web.config is the static data about some status-code and how they will be handled. The responsibility of this section can be generated dynamically by the Application_EndRequest method in Global.asax.
protected void Application_EndRequest()
{
if (Context.Response.StatusCode == 404)
{
Response.Clear();
var routeData = new RouteData();
HttpContextBase currentContext = new HttpContextWrapper(HttpContext.Current);
var lang = RouteTable.Routes.GetRouteData(currentContext).Values["lang"];
routeData.Values["lang"] = lang;
routeData.Values["controller"] = "CustomError";
routeData.Values["action"] = "NotFound";
IController customErrorController = new CustomErrorController();
customErrorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}
}
I believe you can use a session variable to hold current user's ui-culture data.
I don't see a point but, if you don't want to do that, you can follow this tutorial to generate your own routes for MVC custom error page handling.
http://setiabud.blogspot.com.tr/2013/04/handling-404-error-in-aspnet-mvc.html

Asp.net mvc routing - how to allow .html extension in mvc routing

Controller Name is : TestController
Action Name is :HtmlContent
and Url : localhost:53907/en_US/Index.html
I would like to call HtmlContent action from TestController if url which contains .html extension.
I have placed breakpoint in HtmlContent but its not hitting if i enter url like mentioned above,
routes.MapRoute(
name: "MyCustomRoute",
url: "en_US/{pagename}",
defaults: new { controller = "Test", action = "HtmlContent" },
constraints: new {pagename = #".*?$(?<=\.html)" }
);
How to write routing for this requirement?
routes.MapRoute(
name: "MyCustomRoute",
url: "en_US/{pagename}.html",
defaults: new { controller = "Test", action = "HtmlContent" },
constraints: new {pagename = #".*?$(?<=\.html)" }
);
and add code on web.config
<add name="HtmlFileHandler" path="*.html" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
its work for me if any query .please comment

MVC RouteConfig allow /Controller/Action.html

I have an MVC application and am using the standard routeconfig that routes /Controller/Action/Id
I want it to additionally capture /Controller/Action.html as the url and as well and point to /controller/action also.
I am using a jquery library that I have no control over, and a function requires a url that points to a webpage or an image. However, it doesn't appear to understand that ends without an extension(.html, .php etc) is a link to html and throws an error.
Edit: I tried as the commenter below suggested, and still can't seem to get it to work. Here is my route config.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("routeWithHtmlExtension",
"{controller}/{action}.html",
new { controller = "Home", action = "Index" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
This Url works:
http://localhost:14418/Album/Test
This one does not:
http://localhost:14418/Album/Test.html
In web.config
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
...
</system.webServer>
If you set up the following route, it will work:
routes.MapRoute("routeWithHtmlExtension",
"{controller}/{action}.html",
new {controller = "Home", action = "Index" }
);

Resources