Find the applicant's current URl - c#

I'm request for get url :
public Uri GetAbsoluteUri()
{
var request = _httpContextAccessor.HttpContext.Request;
UriBuilder uriBuilder = new UriBuilder();
uriBuilder.Scheme = request.Scheme;
uriBuilder.Host = request.Host.Host;
uriBuilder.Path = request.Path.ToString();
uriBuilder.Query = request.QueryString.ToString();
return uriBuilder.Uri;
}
public string RootPath => Path.Combine(WebRootPath, RootFolderName);
public string GetProductPicturePath()
{
return Path.Combine(GetAbsoluteUri().ToString(), RootFolderName, ProductPictureFolder);
}
public string GetProductMainPicturePath()
{
string path = Path.Combine(GetAbsoluteUri().ToString(), RootFolderName, ProductPictureFolder, ProductMainPictureFolder);
return path;
}
public string GetNewPath()
{
string productMainPicturePath = GetProductMainPicturePath();
return Path.Combine(productMainPicturePath);
}
finally i using the GetNewPath().
, but this will give me the address :
https://localhost/api/Product/GetProductList/Upload/ProductPictureFolder/ProductMainPicture/77777.png
but i have 2 problem with this url :
1 - it not contain port in url https://localhost/api but i need return like this : http://localhost:4200/api
2 - This includes the name of the controller and the ActionName, but I need to like this : https://localhost/Upload/ProductPictureFolder/ProductMainPicture/77777.png
but it return for me this : https://localhost/api/Product/GetProductList/Upload/ProductPictureFolder/ProductMainPicture/77777.png
i not need this /api/Product/GetProductList .
Product : Controller Name
GetProductList : ActionName
How Can I Solve This Problem ???

1 - it not contain port in url https://localhost/api but i need return like this
To get port you can use this snippet :
if (request.Host.Port.HasValue)
uriBuilder.Port = request.Host.Port.Value;
2 - This includes the name of the controller and the ActionName, but I
need to like this :
https://localhost/Upload/ProductPictureFolder/ProductMainPicture/77777.png
I suggest you that set UriBuilder Path based on your needs, not from the request. Something like this:
// Make your Upload file path here
var relativePath = Path.Combine(folderName, filename);
var request = _httpContextAccessor.HttpContext.Request;
var uriBuilder = new UriBuilder
{
Host = request.Host.Host,
Scheme = request.Scheme,
Path = relativePath
};
if (request.Host.Port.HasValue)
uriBuilder.Port = request.Host.Port.Value;
var imageUrl = uriBuilder.ToString();

Related

How to get requesting page controller name in mvc [duplicate]

There's a lot of information for building Uris from Controller and Action names, but how can I do this the other way around?
Basically, all I'm trying to achieve is to get the Controller and Action names from the referring page (i.e. Request.UrlReferrer). Is there an easy way to achieve this?
I think this should do the trick:
// Split the url to url + query string
var fullUrl = Request.UrlReferrer.ToString();
var questionMarkIndex = fullUrl.IndexOf('?');
string queryString = null;
string url = fullUrl;
if (questionMarkIndex != -1) // There is a QueryString
{
url = fullUrl.Substring(0, questionMarkIndex);
queryString = fullUrl.Substring(questionMarkIndex + 1);
}
// Arranges
var request = new HttpRequest(null, url, queryString);
var response = new HttpResponse(new StringWriter());
var httpContext = new HttpContext(request, response)
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
// Extract the data
var values = routeData.Values;
var controllerName = values["controller"];
var actionName = values["action"];
var areaName = values["area"];
My Visual Studio is currently down so I could not test it, but it should work as expected.
To expand on gdoron's answer, the Uri class has methods for grabbing the left and right parts of the URL without having to do string parsing:
url = Request.UrlReferrer.GetLeftPart(UriPartial.Path);
querystring = Request.UrlReferrer.Query.Length > 0 ? uri.Query.Substring(1) : string.Empty;
// Arranges
var request = new HttpRequest(null, url, queryString);
var response = new HttpResponse(new StringWriter());
var httpContext = new HttpContext(request, response)
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
// Extract the data
var values = routeData.Values;
var controllerName = values["controller"];
var actionName = values["action"];
var areaName = values["area"];
To add to gdoran's accepted answer, I found that the action doesn't get populated if a custom route attribute is used. The following works for me:
public static void SetUpReferrerRouteVariables(HttpRequestBase httpRequestBase, ref string previousAreaName, ref string previousControllerName, ref string previousActionName)
{
// No referrer found, perhaps page accessed directly, just return.
if (httpRequestBase.UrlReferrer == null) return;
// Split the url to url + QueryString.
var fullUrl = httpRequestBase.UrlReferrer.ToString();
var questionMarkIndex = fullUrl.IndexOf('?');
string queryString = null;
var url = fullUrl;
if (questionMarkIndex != -1) // There is a QueryString
{
url = fullUrl.Substring(0, questionMarkIndex);
queryString = fullUrl.Substring(questionMarkIndex + 1);
}
// Arrange.
var request = new HttpRequest(null, url, queryString);
var response = new HttpResponse(new StringWriter());
var httpContext = new HttpContext(request, response);
var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));
if (routeData == null) throw new AuthenticationRedirectToReferrerDataNotFoundException();
// Extract the data.
var previousValues = routeData.Values;
previousAreaName = previousValues["area"] == null ? string.Empty : previousValues["area"].ToString();
previousControllerName = previousValues["controller"] == null ? string.Empty : previousValues["controller"].ToString();
previousActionName = previousValues["action"] == null ? string.Empty : previousValues["action"].ToString();
if (previousActionName != string.Empty) return;
var routeDataAsListFromMsDirectRouteMatches = (List<RouteData>)previousValues["MS_DirectRouteMatches"];
var routeValueDictionaryFromMsDirectRouteMatches = routeDataAsListFromMsDirectRouteMatches.FirstOrDefault();
if (routeValueDictionaryFromMsDirectRouteMatches == null) return;
previousActionName = routeValueDictionaryFromMsDirectRouteMatches.Values["action"].ToString();
if (previousActionName == "") previousActionName = "Index";
}
Here is a lightweight way to do this without creating response objects.
var values = RouteDataContext.RouteValuesFromUri(Request.UrlReferrer);
var controllerName = values["controller"];
var actionName = values["action"];
Uses this custom HttpContextBase class
public class RouteDataContext : HttpContextBase {
public override HttpRequestBase Request { get; }
private RouteDataContext(Uri uri) {
var url = uri.GetLeftPart(UriPartial.Path);
var qs = uri.GetComponents(UriComponents.Query,UriFormat.UriEscaped);
Request = new HttpRequestWrapper(new HttpRequest(null,url,qs));
}
public static RouteValueDictionary RouteValuesFromUri(Uri uri) {
return RouteTable.Routes.GetRouteData(new RouteDataContext(uri)).Values;
}
}
#gordon's solution works, but you need to use
return RedirectToAction(actionName.ToString(), controllerName.ToString(),values);
if you want to go to previous action
The RouteData object can access this info:
var controller = RouteData.Values["controller"].ToString();
var action = RouteData.Values["action"].ToString();
This is a method I made to extract url simplified from referrer because I had token (finished with "))/") in my URL so you can extract easily controller and action from this:
private static string GetURLSimplified(string url)
{
string separator = "))/";
string callerURL = "";
if (url.Length > 3)
{
int index = url.IndexOf(separator);
callerURL = url.Substring(index + separator.Length);
}
return callerURL;
}
I don't believe there is any built-in way to retrieve the previous Controller/Action method call. What you could always do is wrap the controllers and action methods so that they are recorded in a persistent data store, and then when you require the last Controller/Action method, just retrieve it from the database (or whatever you so choose).
Why would you need to construct ActionLink from a url ? The purpose of ActionLink is just the opposite to make a url from some data. So in your page just do:
var fullUrl = Request.UrlReferrer.ToString();
Back

Check if it is root domain in string

I'm new to C#,
lets say I have a string
string testurl = "http://www.mytestsite.com/hello";
if (test url == root domain) {
// do something
}
I want to check if that string "testurl" is the root domain i.e http://www.mytestsite.com or http://mytestsite.com etc.
Thanks.
Use the Uri class:
var testUrl = new Uri("http://www.mytestsite.com/hello");
if (testUrl.AbsolutePath== "/")
{
Console.WriteLine("At root");
}
else
{
Console.WriteLine("Not at root");
}
Which nicely deals with any normalization issues that may be required (e.g. treating http://www.mytestsite.com and http://www.mytestsite.com/ the same)
You may try like this:
string testurl = "http://www.mytestsite.com/hello"
if ( GetDomain.GetDomainFromUrl(testurl) == rootdomain) {
// do something
}
You can also try using URI.HostName property
The following example writes the host name (www.contoso.com) of the server to the console.
Uri baseUri = new Uri("http://www.contoso.com:8080/");
Uri myUri = new Uri(baseUri, "shownew.htm?date=today");
Console.WriteLine(myUri.Host);
If the hostname returned is equal to "http://mytestsite.com" you are done.
string testurl = "http://www.mytestsite.com/hello";
string prefix = testurl.Split(new String[] { "//" })[0] + "//";
string url = testurl.Replace(prefix, "");
string root = prefix + url.Split("/")[0];
if (testurl == root) {
// do something
}

Comparing different urls for save domain

Introduction:
I have a start url suppose www.example.com now i run scraper on this url to collect all the internal links belonging to same site and external links.
Problem:
I am using the code below to compare a found url with the main url www.example.com to see if they both have same domain so i take the url as internal url.
Uri baseUri = new Uri(url); //main URL
Uri myUri = new Uri(baseUri, strRef); //strRef is new found link
//domain = baseUri.Host;
domain = baseUri.Host.Replace("www.", string.Empty).Replace("http://", string.Empty).Replace("https://", string.Empty).Trim();
string domain2=myUri.Host.Replace("www.", string.Empty).Replace("http://", string.Empty).Replace("https://", string.Empty).Trim();
strRef = myUri.ToString();
if (domain2==(domain) )
{ //DO STUFF }
Is the above the correct logic ? Because if supposing i get a new url http://news.example.com the domain name found becomes : news.example.com which does not match the domain name of the main url . Is this correct?Should it match or not . And What is a better way if mine is not good enough.
here is a solution to find main domain from subdomain
string url = "http://www.xxx.co.uk";
string strRef = "http://www.news.xxx.co.uk";
Uri baseUri = new Uri(url); //main URL
Uri myUri = new Uri(baseUri, strRef); //strRef is new found link
var domain = baseUri.Host;
domain = baseUri.Host.Replace("www.", string.Empty).Replace("http://", string.Empty).Replace("https://", string.Empty).Trim();
//hrere is solution
string domain2 = GetDomainName(strRef);
strRef = myUri.ToString();
if (domain2 == (domain))
{ //DO STUFF
}
private static string GetDomainName(string url)
{
string domain = new Uri(url).DnsSafeHost.ToLower();
var tokens = domain.Split('.');
if (tokens.Length > 2)
{
//Add only second level exceptions to the < 3 rule here
string[] exceptions = { "info", "firm", "name", "com", "biz", "gen", "ltd", "web", "net", "pro", "org" };
var validTokens = 2 + ((tokens[tokens.Length - 2].Length < 3 || exceptions.Contains(tokens[tokens.Length - 2])) ? 1 : 0);
domain = string.Join(".", tokens, tokens.Length - validTokens, validTokens);
}
return domain;
}

Combine relative baseUri with relative path

I'm looking for a clean way to combine a relative base Uri with another relative path. I've tried the following, but Uri(Uri, string) and UriBuilder(Uri) require absolute Uris (throwing InvalidOperationException: This operation is not supported for a relative URI).
// where Settings.Default.ImagesPath is "~/path/to/images"
// attempt 1
_imagePath = new Uri(Settings.Default.ImagesPath, image);
// attempt 2
UriBuilder uriBuilder = new UriBuilder(Settings.Default.ImagesPath);
uriBuilder.Path += image;
_imagePath = uriBuilder.Uri;
I don't want to do any ugly string manipulation to make sure the base path ends with a trailing slash, etc.
This is still a bit messier than I'd like, but it works.
public static class UriExtensions
{
public static Uri Combine(this Uri relativeBaseUri, Uri relativeUri)
{
if (relativeBaseUri == null)
{
throw new ArgumentNullException("relativeBaseUri");
}
if (relativeUri == null)
{
throw new ArgumentNullException("relativeUri");
}
string baseUrl = VirtualPathUtility.AppendTrailingSlash(relativeBaseUri.ToString());
string combinedUrl = VirtualPathUtility.Combine(baseUrl, relativeUri.ToString());
return new Uri(combinedUrl, UriKind.Relative);
}
}
Here's an example usage:
Uri imageUrl = new Uri("profile.jpg", UriKind.Relative);
Uri baseImageUrl = new Uri("~/path/to/images", UriKind.Relative);
Uri combinedImageUrl = baseImageUrl.Combine(image);
The combinedImageUrl is
~/path/to/images/profile.jpg
Try:
UriBuilder builder = new UriBuilder();
Uri baseUri = builder.Uri;
builder.Path = Settings.Default.ImagesRealtivePath;
if (!builder.Path.EndsWith("/"))
builder.Path += "/";
_imagePath = baseUri.MakeRelativeUri(new Uri(builder.Uri, image));
This will return the string "~/path/to/images/image.jpg".
First of all, thanks for the response on this post!
I made a simplified version of the method, skipping the "complexity" of using the Uri class. The method only takes strings as parameters and is also return a string.
public static string MakeRelativeUrl(params string[] relativePaths)
{
var res = "~/";
foreach (var relativePath in relativePaths)
{
string baseUrl = VirtualPathUtility.AppendTrailingSlash(res);
res = VirtualPathUtility.Combine(baseUrl, relativePath);
}
return res;
}
Above code might be useful for others who wants to expose a method providing this functionality without being dependent on either Uri or VirtualPathUtility, but only simple strings.
Can of course easily be modified to return Uri - still keeping the benefit of parsing string parameters:
public static Uri MakeRelativeUrl(params string[] relativePaths)
{
var res = "~/";
foreach (var relativePath in relativePaths)
{
string baseUrl = VirtualPathUtility.AppendTrailingSlash(res);
res = VirtualPathUtility.Combine(baseUrl, relativePath);
}
return new Uri(res, UriKind.Relative);
}
Usage of both of above code examples:
Image.ImageUrl = MakeRelativeUrl("path", "to", "images", "image.jpg").ToString();
// Image.ImageUrl == "~/path/to/images/image.jpg"
A slightly more generalized version of jrummell's answer that accepts the first parameter to be either an absolute or a relative Uri is:
/// <summary>
/// Combines two <see cref="Uri"/>s.
/// </summary>
/// <param name="baseUri">Relative or absolute base uri.</param>
/// <param name="relativeUri">Uri to be appended.</param>
public static Uri Combine(this Uri baseUri, Uri relativeUri)
{
if (baseUri == null) throw new ArgumentNullException("baseUri");
if (relativeUri == null) throw new ArgumentNullException("relativeUri");
string baseUrl = VirtualPathUtility.AppendTrailingSlash(baseUri.ToString());
string combinedUrl = VirtualPathUtility.Combine(baseUrl, relativeUri.ToString());
return new Uri(combinedUrl, baseUri.IsAbsoluteUri ? UriKind.Absolute : UriKind.Relative);
}
Try:
UriBuilder uriBuilder = new UriBuilder(Settings.Default.ImagesRealtivePath);
uriBuilder.Path += image;
_imagePath = uriBuilder.Uri;
You can just use Path.Combine(string, string) to achieve this. If it's a relative URL the output will be a little funky, but it would be easy enough to correct- or you could simply ignore the issue and most usages should still work.
Path.Combine("~/path/to/images", "image.jpg");
Output: ~/path/to/images\image.jpg

Replace host in Uri

What is the nicest way of replacing the host-part of an Uri using .NET?
I.e.:
string ReplaceHost(string original, string newHostName);
//...
string s = ReplaceHost("http://oldhostname/index.html", "newhostname");
Assert.AreEqual("http://newhostname/index.html", s);
//...
string s = ReplaceHost("http://user:pass#oldhostname/index.html", "newhostname");
Assert.AreEqual("http://user:pass#newhostname/index.html", s);
//...
string s = ReplaceHost("ftp://user:pass#oldhostname", "newhostname");
Assert.AreEqual("ftp://user:pass#newhostname", s);
//etc.
System.Uri does not seem to help much.
System.UriBuilder is what you are after...
string ReplaceHost(string original, string newHostName) {
var builder = new UriBuilder(original);
builder.Host = newHostName;
return builder.Uri.ToString();
}
As #Ishmael says, you can use System.UriBuilder. Here's an example:
// the URI for which you want to change the host name
var oldUri = Request.Url;
// create a new UriBuilder, which copies all fragments of the source URI
var newUriBuilder = new UriBuilder(oldUri);
// set the new host (you can set other properties too)
newUriBuilder.Host = "newhost.com";
// get a Uri instance from the UriBuilder
var newUri = newUriBuilder.Uri;

Categories