Sitecore adding port numbers to all URLs - url

Wondering if anyone has seen this behavior before. My instance of Sitecore 6.6 appends the port number to all the URLs it generates for my site. So for example, a link to the home page should be "https://example.org", but instead it's generated as "https://example.org:443". Everything functions fine with the port numbers, but it's muddling some stuff we're trying to do with SEO and canonicalization. Does anyone know if there's a setting or setup to not produce the port numbers? (I'm sure I could rewrite the URLs by catching them at the appropriate point in the pipeline, but I'm hoping for a simpler way before I jump to that.)

The Sitecore LinkManager is indeed not so clever. We also experienced this issue with a mix of proxy servers and load balancers. To remove the ports, we have created a custom LinkProvider which removes the port if needed (untested code sample):
public class LinkProvider : Sitecore.Links.LinkProvider
{
public override string GetItemUrl(Item item, UrlOptions options)
{
var url = base.GetItemUrl(item, options);
if (url.StartsWith("https://"))
{
url = url.Replace(":443", string.Empty);
}
return url;
}
}
And configure the new LinkProvider:
<configuration xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<linkManager defaultProvider="sitecore">
<providers>
<add name="sitecore" set:type="Website.LinkProvider, Website" />
</providers>
</linkManager>
</sitecore>
</configuration>

This is caused by having the 'scheme' property in the configuration/sitecore/sites/site element of the web.config (or patched config) being set to 'http' explicitly, but making requests over SSL. Removing this, or setting it to 'https' resolves the issue.
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<sites>
<site patch:before="*[#name='website']"
name="my_website"
hostName="my_website.com"
scheme="http"
...
</sites>
</sitecore>
</configuration>

It's a known bug:
https://kb.sitecore.net/articles/913585
There is a patch for releases below 9.1 available here:
https://github.com/SitecoreSupport/Sitecore.Support.93141/releases

I agree with Jan's findings: setting externalPort on the site node in the configuration convinces Sitecore to exclude the port in a generated URL. I did a full write-up on my blog, including using the result for canonical URL tags.
http://findgnosis.com/2017/06/26/hiding-port-urls-produced-sitecores-linkmanager/

LinkManager:
You can cheat the LinkManager by adding port="443" externalPort="80" to your site-definition in <sites>. Don't know if this will cause other issues though.
<configuration>
<sitecore>
<sites>
<site name="website" port="443" externalPort="80" />
</sites>
</sitecore>
</configuration>
MediaManager:
If you know the url, set the Media.MediaLinkServerUrl-setting, to prevent Sitecore from creating the wrong url. Otherwise...
class SslFriendlyMediaProvider : MediaProvider
{
public override string GetMediaUrl(MediaItem item, MediaUrlOptions options)
{
var url = base.GetMediaUrl(item, options);
if(options.AlwaysIncludeServerUrl)
// https://example.com:443/a b?c=123 --> https://example.com/a%20b?c=123
return new Uri(url).AbsoluteUri;
return url;
}
}
Config:
<configuration xmlns:set="http://www.sitecore.net/xmlconfig/set/">
<sitecore>
<mediaLibrary>
<mediaProvider set:type="SslFriendlyMediaProvider, Assembly" />
</mediaLibrary>
</sitecore>
</configuration>

Related

NLog extensibility - How to add custom field using ExtendValues?

I try to add some custom fields to NLog using extensibility.
Part of my nlog.config file looks like that : (simplified for exhibit)
<nlog>
<extensions>
<add assembly="Logzio.DotNet.NLog"/>
</extensions>
<variable name="currentUser" value="test" />
<targets async="true">
<target name="logzio" type="Logzio" token="myToken">
<contextproperty name="currentUser" layout="${currentUser}" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="logzio" />
</rules>
</nlog>
In every controller, I have something like that (I'm using ASP.NET MVC5)
private static Logger logger = LogManager.GetCurrentClassLogger();
Then I send my logs to logzio using
logger.Fatal("Something bad happens");
Right now, currentUser always have the value test, which is logical.
However, despite of the documentation, I don't understand how to dynamically change currentUser value by the ID of my current logged user.
Should I create a sort of factory ? (if yes, how ? I'm not at ease with factories)
Should I change my logger variable ? If so, how ?
A piece of code would be extremly welcome.
Thank you for pointing my out where I'm wrong
EDIT
After #Rolf's answer, I've created this custom layout renderer
[LayoutRenderer("custom-layout")]
public class CustomLayoutRenderer : LayoutRenderer
{
public string IdUser { get; set; }
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
logEvent.Properties.Add("currentUser", "HowToPassCustomDataHere?");
builder.Append("test from custom-layout");
}
}
and I changed the nlog.config accordingly, adding
layout="${message} ${custom-layout}"
to my <target>
However, I still don't understand how to pass custom value to currentUser. In logz.io, I have "HowToPassCustomDataHere?" as a value of currentUser.
(BTW, ${aspnet-user-identity} is great and works fine ; however I'd like to understand how to pass a custom value to my layout renderer. In my case, something like ${aspnet-user-id})
You can try one of these NLog layoutrenderers to acquire the current username:
${aspnet-user-identity} Wiki
${windows-identity} Wiki
You can also create your own custom NLog LayoutRenderer: https://github.com/NLog/NLog/wiki/How-to-write-a-custom-layout-renderer
Example of how to provide it as currentUser:
<target name="logzio" type="Logzio" token="myToken">
<contextproperty name="currentUser" layout="${aspnet-user-identity}" />
</target>

HTTP Error 404.0 - Not Found on action in controller. MVC [duplicate]

I have a project that requires my URLs have dots in the path. For example I may have a URL such as www.example.com/people/michael.phelps
URLs with the dot generate a 404. My routing is fine. If I pass in michaelphelps, without the dot, then everything works. If I add the dot I get a 404 error. The sample site is running on Windows 7 with IIS8 Express. URLScan is not running.
I tried adding the following to my web.config:
<security>
<requestFiltering allowDoubleEscaping="true"/>
</security>
Unfortunately that didn't make a difference. I just receive a 404.0 Not Found error.
This is a MVC4 project but I don't think that's relevant. My routing works fine and the parameters I expect are there, until they include a dot.
What do I need to configure so I can have dots in my URL?
I got this working by editing my site's HTTP handlers. For my needs this works well and resolves my issue.
I simply added a new HTTP handler that looks for specific path criteria. If the request matches it is correctly sent to .NET for processing. I'm much happier with this solution that the URLRewrite hack or enabling RAMMFAR.
For example to have .NET process the URL www.example.com/people/michael.phelps add the following line to your site's web.config within the system.webServer / handlers element:
<add name="ApiURIs-ISAPI-Integrated-4.0"
path="/people/*"
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
Edit
There are other posts suggesting that the solution to this issue is RAMMFAR or RunAllManagedModulesForAllRequests. Enabling this option will enable all managed modules for all requests. That means static files such as images, PDFs and everything else will be processed by .NET when they don't need to be. This options is best left off unless you have a specific case for it.
After some poking around I found that relaxedUrlToFileSystemMapping did not work at all for me, what worked in my case was setting RAMMFAR to true, the same is valid for (.net 4.0 + mvc3) and (.net 4.5 + mvc4).
<system.webserver>
<modules runAllManagedModulesForAllRequests="true">
Be aware when setting RAMMFAR true Hanselman post about RAMMFAR and performance
I believe you have to set the property relaxedUrlToFileSystemMapping in your web.config. Haack wrote an article about this a little while ago (and there are some other SO posts asking the same types of question)
<system.web>
<httpRuntime relaxedUrlToFileSystemMapping="true" />
Edit
From the comments below, later versions of .NET / IIS may require this to be in the system.WebServer element.
<system.webServer>
<httpRuntime relaxedUrlToFileSystemMapping="true" />
I got stuck on this issue for a long time following all the different remedies without avail.
I noticed that when adding a forward slash [/] to the end of the URL containing the dots [.], it did not throw a 404 error and it actually worked.
I finally solved the issue using a URL rewriter like IIS URL Rewrite to watch for a particular pattern and append the training slash.
My URL looks like this: /Contact/~firstname.lastname so my pattern is simply: /Contact/~(.*[^/])$
I got this idea from Scott Forsyth, see link below:
http://weblogs.asp.net/owscott/handing-mvc-paths-with-dots-in-the-path
Just add this section to Web.config, and all requests to the route/{*pathInfo} will be handled by the specified handler, even when there are dots in pathInfo. (taken from ServiceStack MVC Host Web.config example and this answer https://stackoverflow.com/a/12151501/801189)
This should work for both IIS 6 & 7. You could assign specific handlers to different paths after the 'route' by modifying path="*" in 'add' elements
<location path="route">
<system.web>
<httpHandlers>
<add path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" />
</httpHandlers>
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add name="ApiURIs-ISAPI-Integrated-4.0" path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
</location>
MVC 5.0 Workaround.
Many of the suggested answers doesn't seem to work in MVC 5.0.
As the 404 dot problem in the last section can be solved by closing that section with a trailing slash, here's the little trick I use, clean and simple.
While keeping a convenient placeholder in your view:
#Html.ActionLink("Change your Town", "Manage", "GeoData", new { id = User.Identity.Name }, null)
add a little jquery/javascript to get the job done:
<script>
$('a:contains("Change your Town")').on("click", function (event) {
event.preventDefault();
window.location.href = '#Url.Action("Manage", "GeoData", new { id = User.Identity.Name })' + "/";
});</script>
please note the trailing slash, that is responsible for changing
http://localhost:51003/GeoData/Manage/user#foo.com
into
http://localhost:51003/GeoData/Manage/user#foo.com/
Super easy answer for those that only have this on one webpage. Edit your actionlink and a + "/" on the end of it.
#Html.ActionLink("Edit", "Edit", new { id = item.name + "/" }) |
Depending on how important it is for you to keep your URI without querystrings, you can also just pass the value with dots as part of the querystring, not the URI.
E.g. www.example.com/people?name=michael.phelps will work, without having to change any settings or anything.
You lose the elegance of having a clean URI, but this solution does not require changing or adding any settings or handlers.
You might want to think about using dashes instead of periods.
In Pro ASP MVC 3 Framework they suggest this about making friendly URLs:
Avoid symbols, codes, and character sequences. If you want a word
separator, use a dash (/my-great-article). Underscores are unfriendly,
and URL-encoded spaces are bizarre (/my+great+article) or disgusting
(/my%20great%20article).
It also mentions that URLs should be be easy to read and change for humans. Maybe a reason to think about using a dash instead of a dot also comes from the same book:
Don't use file name extensions for HTML pages (.aspx or .mvc), but do use them for specialized file types (.jpg, .pdf, .zip, etc). Web browsers don't care about file name extensions if you set the MIME type appropriately, but humans still expect PDF files to end with .pdf
So while a period is still readable to humans (though less readable than dashes, IMO), it might still be a bit confusing/misleading depending on what comes after the period. What if someone has a last name of zip? Then the URL will be /John.zip instead of /John-zip, something that can be misleading even to the developer that wrote the application.
Would it be possible to change your URL structure?
For what I was working on I tried a route for
url: "Download/{fileName}"
but it failed with anything that had a . in it.
I switched the route to
routes.MapRoute(
name: "Download",
url: "{fileName}/Download",
defaults: new { controller = "Home", action = "Download", }
);
Now I can put in localhost:xxxxx/File1.doc/Download and it works fine.
My helpers in the view also picked up on it
#Html.ActionLink("click here", "Download", new { fileName = "File1.doc"})
that makes a link to the localhost:xxxxx/File1.doc/Download format as well.
Maybe you could put an unneeded word like "/view" or action on the end of your route so your property can end with a trailing / something like /mike.smith/view
As solution could be also considering encoding to a format which doesn't contain symbol., as base64.
In js should be added
btoa(parameter);
In controller
byte[] bytes = Convert.FromBase64String(parameter);
string parameter= Encoding.UTF8.GetString(bytes);
It's as simple as changing path="." to path="". Just remove the dot in the path for ExensionlessUrlHandler-Integrated-4.0 in web.config.
Here's a nice article https://weblog.west-wind.com/posts/2015/Nov/13/Serving-URLs-with-File-Extensions-in-an-ASPNET-MVC-Application
Tried all the solutions above but none of them worked for me. What did work was I uninstalling .NET versions > 4.5, including all its multilingual versions; Eventually I added newer (English only) versions piece by piece. Right now versions installed on my system is this:
2.0
3.0
3.5 4
4.5
4.5.1
4.5.2
4.6
4.6.1
And its still working at this point. I'm afraid to install 4.6.2 because it might mess everything up.
So I could only speculate that either 4.6.2 or all those non-English versions were messing up my configuration.
I was able to solve my particular version of this problem (had to make /customer.html route to /customer, trailing slashes not allowed) using the solution at https://stackoverflow.com/a/13082446/1454265, and substituting path="*.html".
Add URL Rewrite rule to Web.config archive. You need to have the URL Rewrite module already installed in IIS. Use the following rewrite rule as inspiration for your own.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Add trailing slash for some URLs" stopProcessing="true">
<match url="^(.*(\.).+[^\/])$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Redirect" url="{R:1}/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Also, (related) check the order of your handler mappings. We had a .ashx with a .svc (e.g. /foo.asmx/bar.svc/path) in the path after it. The .svc mapping was first so 404 for the .svc path which matched before the .asmx.
Havn't thought too much but maybe url encodeing the path would take care of this.
This is the best solution I have found for the error 404 on IIS 7.5 and .NET Framework 4.5 environment, and without using: runAllManagedModulesForAllRequests="true".
I followed this thread: https://forums.asp.net/t/2070064.aspx?Web+API+2+URL+routing+404+error+on+IIS+7+5+IIS+Express+works+fine and I have modified my web.config accordingly, and now the MVC web app works well on IIS 7.5 and .NET Framework 4.5 environment.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace WebApplication1.Controllers
{
[RoutePrefix("File")]
[Route("{action=index}")]
public class FileController : Controller
{
// GET: File
public ActionResult Index()
{
return View();
}
[AllowAnonymous]
[Route("Image/{extension?}/{filename}")]
public ActionResult Image(string extension, string filename)
{
var dir = Server.MapPath("/app_data/images");
var path = Path.Combine(dir, filename+"."+ (extension!=null? extension:"jpg"));
// var extension = filename.Substring(0,filename.LastIndexOf("."));
return base.File(path, "image/jpeg");
}
}
}

How to override Elmah applicationname set in Web.config

We have a multi-tenanted MVC app, meaning that exactly the same app is published to multiple IIS virtual directories / applications, and then the app its self works out who it is, and skins its self (css) accordingly.
This is all very well, but anything logged by ELMAH in our elmah database gets logged under the same applicationName, as this is pulled out of Web.Config elmah section below where everything would be logged as "MyappName" :
<configuration>
[...]
<elmah>
<security allowRemoteAccess="false" />
<errorLog
type="Elmah.SqlErrorLog, Elmah"
connectionStringName="elmah"
applicationName="MyappName" />
</elmah>
</configuration>
The question is therefore how to override the applicationName setting from web.config with something specific so we can distinguish errors for a given tenant web site.
As this is configurable within the web.config, ELMAH are already providing you with a way to specify the application name when the application is deployed to different locations - it's just a case of making use of it.
This would generally be something that you would manipulate as part of your deployment steps. If you are doing it manually then it's going to be a pain, but it could be easily manipulated by using a web.config transform.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<elmah>
<errorLog applicationName="MyappName" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</elmah>
</configuration>
I wonder if the following might work, if you put the following into your Global.asax:
var service = ServiceCenter.Current;
ServiceCenter.Current = context =>
{
var connectionString = "YOUR CONNECTION STRING";
var container = new ServiceContainer(service(context));
var log = new SqlErrorLog(connectionString) { ApplicationName = "APP NAME HERE" };
container.AddService(typeof(ErrorLog), log);
return container;
};

How can I prevent requests from certain domain in web.config?

I want to restrict one domain for my application in web.config. How can I do it? I just found solution for IIS settings, like
<add ipAddress="some_ip_address" />
but I want to restrict a domain, not IP address
There is no direct way to not allow specific domain.You can restrict certain IPs only.
You can always use nsloopkup to map domain to its IP addresses.
<security>
<ipSecurity allowUnlisted="true">
<clear/> <!-- removes all upstream restrictions -->
<add ipAddress="83.116.19.53"/>
</ipSecurity>
</security>
There is no direct setting in the web.config to do this. However you can create a custom collection in the web.config to list your domains and the write a custom requesthandler or a custom actionfilter that would block the specific domain. However this can very easily be spoofed or bypassed. Here is an example:
Your configsection class:
public class DisallowedDomainsSection : ConfigurationSection
{
// Create a "remoteOnly" attribute.
[ConfigurationProperty("remoteOnly", DefaultValue = "false", IsRequired = false)]
public Boolean RemoteOnly
{
get
{
return (Boolean)this["remoteOnly"];
}
set
{
this["remoteOnly"] = value;
}
}
// Create a "domain" element.
[ConfigurationProperty("domainName")]
public DomainElement Domain
{
get
{
return (DomainElement)this["domainName"]; }
set
{ this["domainName"] = value; }
}
}
Then you declare your config section in the configSections node:
<configSections>
<sectionGroup name="disAllowDomainsGroup">
<section
name="disallowDomains"
type="your.class.definition"
allowLocation="true"
allowDefinition="Everywhere"
/>
</sectionGroup>
</configSections>
Then you declare the action section:
<configuration>
<!-- Configuration section settings area. -->
<disallowDomainsGroup>
<disallowDomain remoteOnly="true">
<domainName="www.google.com" />
</dissallowDomain>
</disallowDomainsGroup>
</configuration>
Finally you create a ActionFilterAttribute to get the list of disallowed domains and redirect/restrict the user if they are originating from the domain.
You can access the newly created webconfig section like this:
DomainsDisallowedSection config =
(DomainsDisallowedSection)System.Configuration.ConfigurationManager.GetSection(
"disallowDomainsGroup/disallowDomains");
and then iterate through your disallowed domains and use
HttpContext.Current.Request.Url.Host
to match the disallowed domain with the request domain. But as previously stated this can be bypassed quite easily by someone who knows how.
In IIS Manager:
Select the desired site.
In the Home pane, open IP Address and Domain Restrictions.
In the Actions pane, launch Edit Feature Settings...
Check the box for Enable domain name restrictions
Click [OK] to exit.
You can now add domain names the same way you add IP addresses.
Note: This cannot be done through web.config. The settings are stored in ApplicationHost.config. You will have to get access to IIS Manager to enable IP and Domain Security though. There is no way around this.
<ipSecurity enableReverseDns="true">
<add ipAddress="192.168.0.1" allowed="false" />
<add domainName="google.com" allowed="false" />
</ipSecurity>

Dots in URL causes 404 with ASP.NET mvc and IIS

I have a project that requires my URLs have dots in the path. For example I may have a URL such as www.example.com/people/michael.phelps
URLs with the dot generate a 404. My routing is fine. If I pass in michaelphelps, without the dot, then everything works. If I add the dot I get a 404 error. The sample site is running on Windows 7 with IIS8 Express. URLScan is not running.
I tried adding the following to my web.config:
<security>
<requestFiltering allowDoubleEscaping="true"/>
</security>
Unfortunately that didn't make a difference. I just receive a 404.0 Not Found error.
This is a MVC4 project but I don't think that's relevant. My routing works fine and the parameters I expect are there, until they include a dot.
What do I need to configure so I can have dots in my URL?
I got this working by editing my site's HTTP handlers. For my needs this works well and resolves my issue.
I simply added a new HTTP handler that looks for specific path criteria. If the request matches it is correctly sent to .NET for processing. I'm much happier with this solution that the URLRewrite hack or enabling RAMMFAR.
For example to have .NET process the URL www.example.com/people/michael.phelps add the following line to your site's web.config within the system.webServer / handlers element:
<add name="ApiURIs-ISAPI-Integrated-4.0"
path="/people/*"
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
Edit
There are other posts suggesting that the solution to this issue is RAMMFAR or RunAllManagedModulesForAllRequests. Enabling this option will enable all managed modules for all requests. That means static files such as images, PDFs and everything else will be processed by .NET when they don't need to be. This options is best left off unless you have a specific case for it.
After some poking around I found that relaxedUrlToFileSystemMapping did not work at all for me, what worked in my case was setting RAMMFAR to true, the same is valid for (.net 4.0 + mvc3) and (.net 4.5 + mvc4).
<system.webserver>
<modules runAllManagedModulesForAllRequests="true">
Be aware when setting RAMMFAR true Hanselman post about RAMMFAR and performance
I believe you have to set the property relaxedUrlToFileSystemMapping in your web.config. Haack wrote an article about this a little while ago (and there are some other SO posts asking the same types of question)
<system.web>
<httpRuntime relaxedUrlToFileSystemMapping="true" />
Edit
From the comments below, later versions of .NET / IIS may require this to be in the system.WebServer element.
<system.webServer>
<httpRuntime relaxedUrlToFileSystemMapping="true" />
I got stuck on this issue for a long time following all the different remedies without avail.
I noticed that when adding a forward slash [/] to the end of the URL containing the dots [.], it did not throw a 404 error and it actually worked.
I finally solved the issue using a URL rewriter like IIS URL Rewrite to watch for a particular pattern and append the training slash.
My URL looks like this: /Contact/~firstname.lastname so my pattern is simply: /Contact/~(.*[^/])$
I got this idea from Scott Forsyth, see link below:
http://weblogs.asp.net/owscott/handing-mvc-paths-with-dots-in-the-path
Just add this section to Web.config, and all requests to the route/{*pathInfo} will be handled by the specified handler, even when there are dots in pathInfo. (taken from ServiceStack MVC Host Web.config example and this answer https://stackoverflow.com/a/12151501/801189)
This should work for both IIS 6 & 7. You could assign specific handlers to different paths after the 'route' by modifying path="*" in 'add' elements
<location path="route">
<system.web>
<httpHandlers>
<add path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" />
</httpHandlers>
</system.web>
<!-- Required for IIS 7.0 -->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add name="ApiURIs-ISAPI-Integrated-4.0" path="*" type="System.Web.Handlers.TransferRequestHandler" verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
</location>
MVC 5.0 Workaround.
Many of the suggested answers doesn't seem to work in MVC 5.0.
As the 404 dot problem in the last section can be solved by closing that section with a trailing slash, here's the little trick I use, clean and simple.
While keeping a convenient placeholder in your view:
#Html.ActionLink("Change your Town", "Manage", "GeoData", new { id = User.Identity.Name }, null)
add a little jquery/javascript to get the job done:
<script>
$('a:contains("Change your Town")').on("click", function (event) {
event.preventDefault();
window.location.href = '#Url.Action("Manage", "GeoData", new { id = User.Identity.Name })' + "/";
});</script>
please note the trailing slash, that is responsible for changing
http://localhost:51003/GeoData/Manage/user#foo.com
into
http://localhost:51003/GeoData/Manage/user#foo.com/
Super easy answer for those that only have this on one webpage. Edit your actionlink and a + "/" on the end of it.
#Html.ActionLink("Edit", "Edit", new { id = item.name + "/" }) |
Depending on how important it is for you to keep your URI without querystrings, you can also just pass the value with dots as part of the querystring, not the URI.
E.g. www.example.com/people?name=michael.phelps will work, without having to change any settings or anything.
You lose the elegance of having a clean URI, but this solution does not require changing or adding any settings or handlers.
You might want to think about using dashes instead of periods.
In Pro ASP MVC 3 Framework they suggest this about making friendly URLs:
Avoid symbols, codes, and character sequences. If you want a word
separator, use a dash (/my-great-article). Underscores are unfriendly,
and URL-encoded spaces are bizarre (/my+great+article) or disgusting
(/my%20great%20article).
It also mentions that URLs should be be easy to read and change for humans. Maybe a reason to think about using a dash instead of a dot also comes from the same book:
Don't use file name extensions for HTML pages (.aspx or .mvc), but do use them for specialized file types (.jpg, .pdf, .zip, etc). Web browsers don't care about file name extensions if you set the MIME type appropriately, but humans still expect PDF files to end with .pdf
So while a period is still readable to humans (though less readable than dashes, IMO), it might still be a bit confusing/misleading depending on what comes after the period. What if someone has a last name of zip? Then the URL will be /John.zip instead of /John-zip, something that can be misleading even to the developer that wrote the application.
Would it be possible to change your URL structure?
For what I was working on I tried a route for
url: "Download/{fileName}"
but it failed with anything that had a . in it.
I switched the route to
routes.MapRoute(
name: "Download",
url: "{fileName}/Download",
defaults: new { controller = "Home", action = "Download", }
);
Now I can put in localhost:xxxxx/File1.doc/Download and it works fine.
My helpers in the view also picked up on it
#Html.ActionLink("click here", "Download", new { fileName = "File1.doc"})
that makes a link to the localhost:xxxxx/File1.doc/Download format as well.
Maybe you could put an unneeded word like "/view" or action on the end of your route so your property can end with a trailing / something like /mike.smith/view
As solution could be also considering encoding to a format which doesn't contain symbol., as base64.
In js should be added
btoa(parameter);
In controller
byte[] bytes = Convert.FromBase64String(parameter);
string parameter= Encoding.UTF8.GetString(bytes);
It's as simple as changing path="." to path="". Just remove the dot in the path for ExensionlessUrlHandler-Integrated-4.0 in web.config.
Here's a nice article https://weblog.west-wind.com/posts/2015/Nov/13/Serving-URLs-with-File-Extensions-in-an-ASPNET-MVC-Application
Tried all the solutions above but none of them worked for me. What did work was I uninstalling .NET versions > 4.5, including all its multilingual versions; Eventually I added newer (English only) versions piece by piece. Right now versions installed on my system is this:
2.0
3.0
3.5 4
4.5
4.5.1
4.5.2
4.6
4.6.1
And its still working at this point. I'm afraid to install 4.6.2 because it might mess everything up.
So I could only speculate that either 4.6.2 or all those non-English versions were messing up my configuration.
I was able to solve my particular version of this problem (had to make /customer.html route to /customer, trailing slashes not allowed) using the solution at https://stackoverflow.com/a/13082446/1454265, and substituting path="*.html".
Add URL Rewrite rule to Web.config archive. You need to have the URL Rewrite module already installed in IIS. Use the following rewrite rule as inspiration for your own.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Add trailing slash for some URLs" stopProcessing="true">
<match url="^(.*(\.).+[^\/])$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Redirect" url="{R:1}/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Also, (related) check the order of your handler mappings. We had a .ashx with a .svc (e.g. /foo.asmx/bar.svc/path) in the path after it. The .svc mapping was first so 404 for the .svc path which matched before the .asmx.
Havn't thought too much but maybe url encodeing the path would take care of this.
This is the best solution I have found for the error 404 on IIS 7.5 and .NET Framework 4.5 environment, and without using: runAllManagedModulesForAllRequests="true".
I followed this thread: https://forums.asp.net/t/2070064.aspx?Web+API+2+URL+routing+404+error+on+IIS+7+5+IIS+Express+works+fine and I have modified my web.config accordingly, and now the MVC web app works well on IIS 7.5 and .NET Framework 4.5 environment.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace WebApplication1.Controllers
{
[RoutePrefix("File")]
[Route("{action=index}")]
public class FileController : Controller
{
// GET: File
public ActionResult Index()
{
return View();
}
[AllowAnonymous]
[Route("Image/{extension?}/{filename}")]
public ActionResult Image(string extension, string filename)
{
var dir = Server.MapPath("/app_data/images");
var path = Path.Combine(dir, filename+"."+ (extension!=null? extension:"jpg"));
// var extension = filename.Substring(0,filename.LastIndexOf("."));
return base.File(path, "image/jpeg");
}
}
}

Resources