We have an existing CMS implementation, episerver 7.1, that has a .NET 4.0 app pool and is built against .NET 4.0.
This CMS is forms based and request authentication has been disabled for it. We have a custom page type that has an URL property, and we sometimes use a custom URI scheme in this URL property to dynamically look up catalog links in the code behind, mpc://16403 where 16403 us a unique ID for the product that is not market specific. [This allows the client to add the links once, and then the system looks up the correct market specific link]
We encountered an issue with a service on the machine and had to install .NET 4.5.
Suddenly we noticed that the custom links were being corrupted, changing mpc://16403 to mpc://0.0.64.19/
For some reason, after the installation of .NET 4.5, our custom URL is being converted to an IP address. None of the configuration has changed, only the installation of .NET 4.5.
Does anyone know why this is happening and how we can stop it from happening?
I would bet that under the covers, System.Uri is being used. If you look through the class reference, you will see that the class parses the string that is passed in to break it into its component parts (scheme, host, etc). In this case, it looks like the parsing logic was modified to assume that a hostname that consists of numbers is an IP address. As far as how to best handle this problem, it looks like you may want to either use strings (probably a bad idea) or a custom protocol handler.
OK, there seems to be a bug in how .NET 4.5 handles the System.Uri class.
Specifically it always applies IPAddress.Parse to the host, even if the scheme is unknown. This is wrong as not all 'hosts' are IP addresses.
The following code snippet produces mpc 00.00.64.19 in .NET 4.5 but in .NET 4.0 and .NET 4.5.1 it produces the correct mpc 16403
System.Uri myUri = new System.Uri("mpc://16403");
Console.WriteLine(myUri.Scheme + " " + myUri.Host);
So, if you want to use custom schemes with any class/feature derived from System.Uri do not use .NET 4.5 and go straight to .NET 4.5.1
Related
I have a project that uses ado.net dataservices. This project was originally developed in VS2005 and IIS6 but I am now porting it to IIS7 standards. I've run into a snag when trying to update existing records, the put operation (to the service) fails and prompts the following browser alert:
The URI 'http://localhost:6188/services/Datatracker.svc/provider' is not valid for PUT operation. The URI must point to a single resource for PUT opeations.
I imagine this is because the URI is being treated as a folder, and I know that this can be corrected through configuration but I'm having trouble finding the specific settings
Any assistance would be appreciated.
So as it turns out this is invalid syntax for put and delete requests:
http://localhost:6188/services/Datatracker.svc/provider
Valid odata syntax is: (OLKM represents the calue of the keyfield that uniquely identifies the record)
http://localhost:6188/services/Datatracker.svc/provider('OLKM')
Old asp.net + iis6 allowed you to cheat your way around this requirement, but iis7 & .net 3.5+ requires you to use the correct syntax.
I want to make a "properties style web form" that shows the application version for various .NET applications.
If I know the URL e.g. /someapp/default.aspx is it possible via reflection to execute that page and figure out the assembly version?
It's quite easy to find the executing assembly version, but without modifying the other application, is it possible?
Both the property page and the other application is running on the same server and in the same application pool.
Update: I've had some luck with
var url = "~/SomeApp/default.aspx";
var appType = System.Web.Compilation.BuildManager.GetCompiledType(url);
But navigating appType to find the assembly file version is not the same everytime.
Without modifying the web application to expose the version number through some URL-based retrieval (a simple page GET being the easy, obvious one), you're going to need to find a way to figure out where the DLL for the web application is from the URL.
If you can know the DLL's location, either by some convention (e.g. /appX/ is always at D:\Sites\appX\bin\appX.dll) or some configuration (you manually enter where each URL base's DLL is in a database), then you can retrieve that DLL's assembly version using the following code:
Assembly assembly = Assembly.LoadFrom("MyAssembly.dll");
Version ver = assembly.GetName().Version;
Code taken from this question.
Edit:
I've had a little look around, and there are some APIs to inspect the IIS configuration, so this is certainly a route to explore if you're trying to get from the URL to the assembly location. This question has an example of getting the physical path from the application/site name, for example. Microsoft.Web.Administration is the assembly to explore.
The ASP.NET engine streams nothing but HTML, javascript, etc.. to the client. There is nothing left of the assembly that gets passed in the response that can show what version of .net/asp.net that the application is running unless the developer on the server side adds it.
That said, you can gather some information from a utility at http://uptime.netcraft.com/up/graph that will give you some server information. Not down to the assembly version, but this is as close as I believe you are going to get.
You may implement custom HttpModule, put it to the bin folder of each application that you wish to monitor and append register this module in web.config files. In this module for example you should handle request, retrieve all required information and put it to response cookie.
I am trying to create url routing like this
http://msdn.microsoft.com/en-us/magazine/dd347546.aspx
but I am having few questions , first why he is adding lines to the web.config , I tested it and it didnt appear that they're doing something as I commented them and nothing major appeared
second I am having this line of code that is crashing
var display = BuildManager.CreateInstanceFromVirtualPath(_virtualPath,typeof(Page)) as IProfileHandler;
when casted as ihttphandler it's working , but when I am casting it to iprofilehandler(which is implemeting ihttphandler) it's giving null !
This article is quite old as it's written before ASP.NET 4.0 was released.
Routing is now a core component of ASP.NET 4.
See this one instead:
http://weblogs.asp.net/scottgu/archive/2009/10/13/url-routing-with-asp-net-4-web-forms-vs-2010-and-net-4-0-series.aspx
These are really two questions here:
Why he is adding lines to the web.config - Web Configuration in .NET 4.0 applications has been greatly streamlined. A lot of the configuration that was done per-application is now included in the lower level web configuration (machine wide) (read). This means you don't need to add that configuration data in, its already done for you.
You're issue with BuildManager returning null. We'd need to see a little more code than that.
The challenge is to determine whether ASP.NET is enabled within IIS7 in a reliable and correct way.
Enabling/Disabling is done in this case by going into:
Server Manager ->
Roles ->
Web Server (IIS) ->
Remove Role Services ->
Remove ASP.NET
The natural place to determine this should be within the applicationHost.config file. However, with ASP.NET enabled or disabled, we still have the "ManagedEngine" module available, and we still have the isapi filter record in the tag.
The best I can find at the moment is to check if the <isapiCgiRestriction> tag includes the aspnet_isapi.dll, or that the ASPNET trace provider is available.
However these aren't detecting the presence of the ASP.NET config directly, just a side effect that could conceivably be reconfigured by the user.
I'd rather do this by examining the IIS configuration/setup rather than the OS itself, if possible, although enumerating the Roles & Services on the server might be acceptable if we can guarantee that this technique will always work whenever IIS7 is used.
Update
Thanks for the responses. Clarifying exactly what I want to do, I'm pulling settings from a variety of places in the server's configuration into a single (readonly) view to show what the user needs to have configured to allow the software to work.
One of the settings I need to bring in is this one:
The one highlighted in red.
I don't need to manipulate the setting, just reproduce it. I want to see whether the user checked the ASP.NET box when they added the IIS role to the server, as in this example they clearly didn't.
I'd like to do this by looking at something reliable in IIS rather than enumerating the role services because I don't want to add any platform specific dependencies on the check that I don't need. I don't know if it will ever be possible to install IIS7 on a server that doesn't have the Roles/Services infrastructure, but in preference, I'd rather not worry about it. I also have a load of libraries for scrubbing around IIS already.
However, I'm also having trouble finding out how to enumerate the Roles/Services at all, so if there's a solution that involves doing that, it would certainly be useful, and much better than checking the side effect of having the ASPNET trace provider lying around.
Unfortunately, if you don't check the ASP.NET button, you can still get the ManagedEngine module in the IIS applicationHost.config file, so it's not a reliable check. You can also have ASP.NET mapped as an isapi filter, so checking them isn't enough. These things are especially problematic in the case where ASP.NET was installed but has been removed.
It looks like the best solution would be to examine the Role Services. However, API information on this is looking pretty rare, hence the cry for help.
The absolute way to know if they checked that or not is to search the following registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp\Components
In there you should see two values set to 1, ASPNET and NetFxEnvironment and NetFxExtensibility. This registry key is the IIS Setup key that contains all the components that have been enabled in IIS.
Determining if asp.net is even an installed feature (prerequisite for enabling it) can be done through PowerShell, which implies there is .net api out there for it if you dig hard enough. The PowerShell methods:
Import-Module servermanager
Get-WindowsFeature web-asp-net
Which will return an object of type Microsoft.Windows.ServerManager.Commands.Feature. The installed property is boolean and indicates whether or not the feature is installed.
So do you want the easy way? Make a nice pretty .aspx page that displays as HTML with an error block in a div in a placeholder saying "You need to install ASP.NET" and have it change on ASP.NET being installed to instead say "ASP.NET is installed" and then just have the tool launch this webpage in the default browser after copying it to the directory identified in IIS as the *:80 site (or create the directory mapping in IIS programmatically by altering the XML and then removing it later)
May not be the most elegant but it does ensure that testing shows what features are truly installed versus what's in an XML file.
Because that will scream "do it the lazy ignorant way" I'll remind you that the only way for me to know in javascript what features I can use is to test them before I try to use them, or assume they're there and watch it blow up. My point is, it doesn't matter what gets reported in a file, it matters what you can actually use. Just because C:\Windows\Micrsoft.Net\Framework\v3.xxxxxxxx exists and has files doesn't mean the dll's are registered in the GAC, does it?
I have an ASP.NET application originally deployed to a .Net 1.1 Framework on Windows 2000 server which i'm now using on a Windows 2008 Server using 2.0.50727. We use the tilde (~) to resolve to an absolute path in many areas of the application and it works for things like asp:hyperlink controls (with run-at server tags), but for our bound datagrid controls which are using HyperLinkColumns to create links based on ID values returned from our database, the tilde is getting written to the page.
This code:
HyperLinkColumn oLink = new HyperLinkColumn();
oLink.DataNavigateUrlField = "IdField";
oLink.DataNavigateUrlFormatString = "~/Here{0}.aspx";
is dumping this to the page:
<a href="~/Here171201.aspx">
What changed between versions of IIS or .NET Framework could be causing this functionality to no longer work? The Tilde was definitely resolving in 1.1 - I have the exact same code deployed on a dozen 1.1 Framework servers in our organization. Unfortunately, the class that sets the DataNavigateUrlFormatString doesn't have access to the Page, so I'll have to do some kludging to insert the Page.ResolveUrl work around...
I'm not aware of anything changing, but I don't use HyperLinkColumns (I prefer the control which the Template column provides) so I've not looked for any changes .
One possibility as a proverbial band aid is to change this line:
oLink.DataNavigateUrlFormatString = "~/Here{0}.aspx";
to this:
oLink.DataNavigateUrlFormatString = Page.ResolveUrl("~/Here{0}.aspx");
If memory serves there was some issues when going to Master Pages and using the '~' from User Controls, but it's been a while since I read anything like that.
I don't think that the HyperlinkColumn of a Datagrid automatically resolves the URL into an absolute path. IIRC, the DataNavigateUrlFormatString property internally calls String.Format() only on the supplied format. Are you sure this worked correctly on .NET 1.1? IIRC, .NET 1.1 did not have tilde-based automatic URL resolution.
In my opinion, you should use the solution presented by Stephen (call Page.ResolveUrl manually.)