I have 1 website on IIS ("myWebsite") and another inside this one ("secondWebsite") as an application. Both are ASP.NET Mvc websites.
I have a method who works perfectly on the first one :
public static string AbsolutePath(this UrlHelper url, string path)
{
Uri requestUrl = url.RequestContext.HttpContext.Request.Url;
string absoluteAction = string.Format("{0}{1}", requestUrl.GetLeftPart(UriPartial.Authority), path);
return absoluteAction;
}
The result is : http://myWebsite.com/path
I have the same method in the second Website, the result is the same, that's logic, but I don't want it !
The result should be : myWebsite.com/secondWebsite/path. (miss the http:// cause of spam prevention ^^).
Is there a good way to do that ?
Thanks.
You could try using
string absoluteAction = string.Concat(Request.Url.Authority,
Request.ApplicationPath, path);
Can you not use Server.ResolveUrl("~/Path"); as that rebases from application root.
Related
We are using Nancy framework for our application which is self-hosted in console application.
The problem appears when loading the URL without trailing slash.
Let's say we are hosting the page in
http://host.com:8081/module/
It then serves us am html page which has resources with a relative path like this:
content/scripts.js
Everything works well when you enter a url such as
// Generates a resource url 'http://host.com:8081/module/content/scripts.js'
// which is good
http://host.com:8081/module/
But when we leave out a trailing slash, the resource url is
// Generates a resource url 'http://host.com:8081/content/scripts.js'
// which is bad
http://host.com:8081/module
Is there any way to make redirection to trailing slash version? Or at least detect if trailing slash exists or not.
Thanks!
This feels a bit hacky but it works:
Get["/module/"] = o =>
{
if (!Context.Request.Url.Path.EndsWith("/"))
return Response.AsRedirect("/module/" + Context.Request.Url.Query, RedirectResponse.RedirectType.Permanent);
return View["module"];
};
The Request accessible from Context lets you see whether the path has the trailing slash or not and redirect to a 'slashed' version.
I wrapped this up as an extension method (which works for my very simple use case):
public static class NancyModuleExtensions
{
public static void NewGetRouteForceTrailingSlash(this NancyModule module, string routeName)
{
var routeUrl = string.Concat("/", routeName, "/");
module.Get[routeUrl] = o =>
{
if (!module.Context.Request.Url.Path.EndsWith("/"))
return module.Response.AsRedirect(routeUrl + module.Request.Url.Query, RedirectResponse.RedirectType.Permanent);
return module.View[routeName];
};
}
}
To use in a module:
// returns view "module" to client at "/module/" location
// for either "/module/" or "/module" requests
this.NewGetRouteForceTrailingSlash("module");
This is worth reading though before going with a solution such as this
I have a view (with one or more images) that I also want to use as the body of an email message. The Model serving the view uses Url.Content() to retrieve the absolute image path. This approach works fine for web pages, but when I render the exact same view as the body of the email, then the image can not be found which is suggested by the incomplete path from the rendered html.
<img src="/Media/fe882a1d-3b77-4264-ab91-cade985ecbed.JPG"/>
I know that this problem can be fixed if I could access the full url such as with Url.Action with the
Request.Url.Scheme
overload for protocol. Is there a way to determine the fully qualified URL from Url.Content?
Try writting your own url extension method and resolve with the help of Uri.GetLeftPart & UriPartial.Authority
public static class UrlExtensions
{
public static string AbsoluteContent(this UrlHelper urlHelper
, string contentPath)
{
Uri requestUrl = urlHelper.RequestContext.HttpContext.Request.Url;
string absolutePath = string.Format("{0}{1}",
requestUrl.GetLeftPart(UriPartial.Authority),
urlHelper.Content(contentPath));
return absolutePath;
}
}
Then use Url.AbsoluteContent("~/media/image.jpeg") in your pages. It will render http://domain/media/image.jpeg
There are a lot of material written about Subdomain routing in ASP.NET MVC. Some of them use Areas as target for subdomains other use another Controllers.
There are some of them:
Subdomains for a single application with ASP.NET MVC
Asp.Net MVC 2 Routing SubDomains to Areas
MVC 3 Subdomain Routing
MVC-Subdomain-Routing on Github
They do all explain how to accept and route requests with subdomain.
But:
None of them explains how to generate URLs with subdomain. I.e. I tried #Html.RouteLink("link to SubDomain", "SubdomainRouteName") but what it ignores subdomain and generates url without it
How to deal with the same names of controllers from different areas. All those solutions (they use namespaces for these purpose) throw exception that exist several controllers and suggest using namespaces :)
Purpose:
create mobile version of site using subdomain
I've wrote a post on how I use subdomain routing in my application. The source code is available on the post, but I'll try to explain how I did my custom RouteLink method.
The helper method uses the RouteTable class to get the Route object based on the current Url and cast it to a SubdomainRoute object.
In my case all routes are defined using the SubdomainRoute and everytime I need to add a link to some other page I use my custom RouteLink helper, this is why I consider this cast safe. With the SubdomainRoute variable available I'm able to get the subdomain name and then build the Url using the UriBuilder class.
This is the code I'm currently using.
public static IHtmlString AdvRouteLink(this HtmlHelper htmlHelper, string linkText, string routeName, object routeValues, object htmlAttributes)
{
RouteValueDictionary routeValueDict = new RouteValueDictionary(routeValues);
var request = htmlHelper.ViewContext.RequestContext.HttpContext.Request;
string host = request.IsLocal ? request.Headers["Host"] : request.Url.Host;
if (host.IndexOf(":") >= 0)
host = host.Substring(0, host.IndexOf(":"));
string url = UrlHelper.GenerateUrl(routeName, null, null, routeValueDict, RouteTable.Routes, htmlHelper.ViewContext.RequestContext, false);
var virtualPathData = RouteTable.Routes.GetVirtualPathForArea(htmlHelper.ViewContext.RequestContext, routeName, routeValueDict);
var route = virtualPathData.Route as SubdomainRoute;
string actualSubdomain = SubdomainRoute.GetSubdomain(host);
if (!string.IsNullOrEmpty(actualSubdomain))
host = host.Substring(host.IndexOf(".") + 1);
if (!string.IsNullOrEmpty(route.Subdomain))
host = string.Concat(route.Subdomain, ".", host);
else
host = host.Substring(host.IndexOf(".") + 1);
UriBuilder builder = new UriBuilder(request.Url.Scheme, host, 80, url);
if (request.IsLocal)
builder.Port = request.Url.Port;
url = builder.Uri.ToString();
return htmlHelper.Link(linkText, url, htmlAttributes);
}
private static IHtmlString Link(this HtmlHelper htmlHelper, string text, string url, object htmlAttributes)
{
TagBuilder tag = new TagBuilder("a");
tag.Attributes.Add("href", url);
tag.InnerHtml = text;
tag.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
I have this ASP.NET MVC application that I now want to separate out the image links to a CDN.
At this moment, images typically have this markup code:
<%= Html.ActionLinkWithImage("/Content/Img/Image1.png" ...
This works fine in development using the local web server (Cassini), and also when published the prod server.
But now I want the production URL to something like:
http://cdn.com/Img/Image1.png
How do I get this to work in an easy way, so that it works seamlessly in dev and after published to prod?
You can create a URL extension method that will, depending on a value from the Web.config file (or something else), generate the debug URL or the live URL.
public static MvcHtmlString CDNImageLink(this UrlHelper url, string imageName)
{
string urlFormat;
if((bool)ConfigurationManager.AppSettings["Debug"])
urlFormat = "/Content/Img/{0}";
else
urlFormat = "http://cdn.com/Img/{0}";
return MvcHtmlString.Create(string.Format(urlFormat, imageName));
}
You can then use this extension method anywhere you need an image url (including Html extension methods):
public static MvcHtmlString ActionLinkWithImage(this HtmlHelper html, string imageName)
{
UrlHelper Url = new UrlHelper(html.ViewContext.RequestContext);
string imageUrl = Url.CDNImageLink(imageName);
// generate the rest of the ActionLink using the imageUrl
}
Make sure you have the using statement for the namespace where the Url extension method is located at the top of the file where you declared the HTML extension method, otherwise it will not recognize it.
You can also modify your host file to redirect your cdn domain to another IP address. I use this to redirect static.myresources.com to localhost all the time and it keeps your html pretty clean.
I'd like to create URLs based on the URL used by the client for the active request. Is there anything smarter than taking the current HttpServletRequest object and it's getParameter...() methods to rebuilt the complete URL including (and only) it's GET parameters.
Clarification: If possible I want to resign from using a HttpServletRequest object.
Well there are two methods to access this data easier, but the interface doesn't offer the possibility to get the whole URL with one call. You have to build it manually:
public static String makeUrl(HttpServletRequest request)
{
return request.getRequestURL().toString() + "?" + request.getQueryString();
}
I don't know about a way to do this with any Spring MVC facilities.
If you want to access the current Request without passing it everywhere you will have to add a listener in the web.xml:
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
And then use this to get the request bound to the current Thread:
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
Instead of using RequestContextHolder directly, you can also use ServletUriComponentsBuilder and its static methods:
ServletUriComponentsBuilder.fromCurrentContextPath()
ServletUriComponentsBuilder.fromCurrentServletMapping()
ServletUriComponentsBuilder.fromCurrentRequestUri()
ServletUriComponentsBuilder.fromCurrentRequest()
They use RequestContextHolder under the hood, but provide additional flexibility to build new URLs using the capabilities of UriComponentsBuilder.
Example:
ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentRequestUri();
builder.scheme("https");
builder.replaceQueryParam("someBoolean", false);
URI newUri = builder.build().toUri();
Java's URI Class can help you out of this:
public static String getCurrentUrl(HttpServletRequest request){
URL url = new URL(request.getRequestURL().toString());
String host = url.getHost();
String userInfo = url.getUserInfo();
String scheme = url.getProtocol();
String port = url.getPort();
String path = request.getAttribute("javax.servlet.forward.request_uri");
String query = request.getAttribute("javax.servlet.forward.query_string");
URI uri = new URI(scheme,userInfo,host,port,path,query,null)
return uri.toString();
}
in jsp file:
request.getAttribute("javax.servlet.forward.request_uri")
You can also add a UriComponentsBuilder to the method signature of your controller method. Spring will inject an instance of the builder created from the current request.
#GetMapping
public ResponseEntity<MyResponse> doSomething(UriComponentsBuilder uriComponentsBuilder) {
URI someNewUriBasedOnCurrentRequest = uriComponentsBuilder
.replacePath(null)
.replaceQuery(null)
.pathSegment("some", "new", "path")
.build().toUri();
//...
}
Using the builder you can directly start creating URIs based on the current request e.g. modify path segments.
See also UriComponentsBuilderMethodArgumentResolver
If you need the URL till hostname and not the path use Apache's Common Lib StringUtil, and from URL extract the substring till third indexOf /.
public static String getURL(HttpServletRequest request){
String fullURL = request.getRequestURL().toString();
return fullURL.substring(0,StringUtils.ordinalIndexOf(fullURL, "/", 3));
}
Example: If fullURL is https://example.com/path/after/url/ then
Output will be https://example.com
System.out.println(((HttpServletRequest)request).getRequestURI());
I used it. hope it's useful.