Why is DynamicData not working on new 2012 Server? - c#

I have an ASP.Net website that uses DynamicData controls that works on it's current server and locally, but any page with dynamic controls fails on the new 2012 server i'm setting up. Everything is pretty much identical from an application perspective.
Error:Exception type: InvalidOperationException
Exception message: Could not determine a MetaTable. A MetaTable could not be determined for the data source '' and one could not be inferred from the request URL. Make sure that the table is mapped to the data source, or that the data source is configured with a valid context type and table name, or that the request is part of a registered DynamicDataRoute.
Is there a missing config, feature, or role missing possibly?

It turns out the app pool was not configured correctly. It needed to be set to .Net 2.0 - integrated pipeline.

Related

ASP.NET Core 6.0+: How to get the current (case-sensitive) IIS Website Name?

I'm trying to get the name of my ASP.NET 6 app hosted in IIS. What I need is exactly this name with proper casing:
In .NET Framework 4.8, this name was provided by HttpRequest.ApplicationPath and it was returned with proper casing (as configured in IIS, not as in the coming request's URL). However, it doesn't exist in .NET 6.
I tried:
HttpContext.Request.PathBase, but it returns the path exactly as in the requesting URL, not as in the IIS
injecting IServerAddressesFeature and IWebHostEnvironment, but none of them contains the name from IIS with correct casing
IServerAddressesFeature, but also didn't find anything relevant here
getting server variables: IServerVariablesFeature serverVars = HttpContext.Features.Get<IServerVariablesFeature>() and then the IIS Site name: string iis_version = serverVars["INSTANCE_NAME"] (see documentation here), but it returns the app name in capital letters (MYSITE.WEB)
Does anyone know how to get this site's name as configured in IIS (with proper casing)?
TL;DR:
Use the APPL_MD_PATH server-variable.
This contains the IIS Metabase Application Path string. (AFAIK, "MD" stands for "Meta-database").
Quoteth the docs:
https://learn.microsoft.com/en-us/previous-versions/iis/6.0-sdk/ms524602(v=vs.90)?redirectedfrom=MSDN
"APPL_MD_PATH - Retrieves the metabase path of the application."
Like so:
// This code assumes HttpContext is available, such as in a Middleware method or `Controller` subclass.
using Microsoft.AspNetCore.Http;
String? iisMetabasePath = httpContext.GetServerVariable("APPL_MD_PATH");
// or (long-form):
String? iisMetabasePath = HttpContextServerVariableExtensions.GetServerVariable( httpContext, "APPL_MD_PATH" );
Then just trim-off the /LM/W3SVC/ part.
Note that when you run your code outside of IIS, such as with ASP.NET Core's development server, all IIS-specific data, like "APPL_MD_PATH" won't be available, so make sure you're handling that case too.
Original research: What happened to ApplicationRoot?
Time to bust-out ILSpy...
HttpRequest.ApplicationPath is HttpRuntime.AppDomainAppVirtualPath.
HttpRuntime.AppDomainAppVirtualPath is VirtualPath.GetVirtualPathStringNoTrailingSlash(HttpRuntime._theRuntime._appDomainAppVPath).
HttpRuntime._theRuntime._appDomainAppVPath is set in HttpRuntime.Init().
HttpRuntime.Init() sets _appDomainAppVPath from HttpRuntime.GetAppDomainString(".appVPath")).
"AppDomain Strings" are small serializable scalar values that are associated with each AppDomain.
Generally speaking, ASP.NET in .NET Framework (aka System.Web) creates a new AppDomain for each Application Scope in IIS.
And of course, AppDomains no-longer exist in .NET Core and later.
So let's find out where the String value for ".appVPath" comes from...
System.Web.Hosting.ApplicationManager::PopulateDomainBindings sets dict.Add(".appVPath", appVPath.VirtualPathString)
"domain bindings" in this context refers to AppDomain bindings: nothing at all to do with DNS domain-names or Host header bindings in IIS. Yay for overloaded terminology.
PopulateDomainBindings is called by System.Web.Hosting.ApplicationManager::CreateAppDomainWithHostingEnvironment.
And it gets virtualPath: VirtualPath.Create(appHost.GetVirtualPath()).
appHost.GetVirtualPath() is IApplicationHost.GetVirtualPath().
There are 2 in-box implementations: System.Web.Hosting.ISAPIApplicationHost and System.Web.Hosting.SimpleApplicationHost. We're interested in ISAPIApplicationHost.
ISAPIApplicationHost gets its virtualPath from the runtime argument to String appId and String appPath in the IAppManagerAppDomainFactory.Create method.
And IAppManagerAppDomainFactory is a COM interface used directly by IIS.
The plot thickens...
At this point I got lost trawling through the legacy IIS 6 ISAPI documentation, looking for traces of the original COM definition of IAppManagerAppDomainFactory but came up empty-handed.
It's probably handled by webengine4.dll which is a native DLL and I don't have the time to bust-out Ghidra right now...
I did notice that the ISAPI request entrypoint method HttpExtensionProc (and its LPEXTENSION_CONTROL_BLOCK parameter) do not contain the IIS Application Scope AppId or Virtual Path, which surprised me - but most importantly: this suggests the value must likely come from the GetServerVariable or ServerSupportFunction callbacks....
However that's likely a waste of time anyway IIS 6 is not IIS7+ and IIS7+'s interfaces are no-longer called "ISAPI" but instead called just "IIS Native-Code API" (that's the most plain and boring API name I've seen in a while...).
So, starting with the "IIS Native-Code API" documentation I quickly found the IWpfApplicationInfoUtil::GetApplicationPropertiesFromAppId method (here "WPF" means "Worker Process Framework", and is entirely unrelated to the other UI-related WPF).
I also found the same data exposed via the IMetadataInfo.GetMetaPath() method (which returns a string of the form "LM/WEBROOT/AppHost/{SiteId}").
So how does an application get a IWpfApplicationInfoUtil interface reference?
IWorkerProcessFramework->GetWpfInterface(WPF_APPLICATION_INFO_UTIL_ID)->GetApplicationPropertiesFromAppId
So how do you get IWorkerProcessFramework?
It's passed as a parameter into your w3wp.exe worker DLL.
So let's see what AspNetCoreModuleV2 does...
Actually AspNetCoreModuleV2 uses IIS's IHttpApplication, derp.
IHttpApplication exposes GetAppConfigPath() which also returns a string of the form /LM/W3SVC/1/ROOT/{Site Name}.
ASP.NET Core seems to use it in a few places.
At this point I gave up as it's now 6:20am, but that was a fun dive!

Unable to load type System.Collections.Generic.List`1 required for deserialization

I have ASP.NET website running on IIS. App uses standard .NET cache (HttpContext.Current.Cache). In some cases after new deployment I'm getting error
Unable to load type System.Collections.Generic.List`1 required for deserialization.
I'm trying to understand why I get this error and looking for the best way to resolve it.
As per my understanding - cache object includes older version of the "type" and after next deployment application uses new version of type. And in this case the best way to fix it - clear IIS cache?

Loading routes according to HTTP_HOST in MVC4

I have a multi-tenant MVC4 website in which I want to set up the the RouteTable according incoming host and domain name eg www.domain1.com, www.domain2.com and www.domain3.co.uk could have one or more additional values appended to the route table according to the host and domain anem.
The DNS server has been set up with a number of distinct zones with hosts, and I'm using IIS7 as a 'custom web server' rather than using Visual Studio 2012 Development Server so that I get the correct HTTP_HOST value available to me in the Request variable.
The problem I have with IIS7 is that to the value of HttpContext.Current.Request.ServerVariables["HTTP_HOST"] is not available if you try to call it in the RegisterRoutes method where all the other route mapping is done.
The main thing I need to do is determine at some point in the request pipeline the the value that will eventually end up in the HTTP_HOST server variable . That value needs storing and the route table appropriately updated before it gets used.
Will it need an Http Module, Http Handler, Action Filter or somesuch? Or is there some other place in the MVC pipeline that I can do this.
Crispin
There's no built in support for routing based on host that I'm aware of, but you can create a Route subclass that pulls the host value in. Here's an example:
http://blog.maartenballiauw.be/post/2009/05/20/aspnet-mvc-domain-routing.aspx
That's written for MVC3, but should work fine in MVC4.

RequestContext Via Property has Machine Name instead of URL in IIS

I am doing some work with OAuth and need to get the URL of the request. To do this I am doing the following:
operationContext.RequestContext.RequestMessage.Properties.Via
This was working great in Visual Studio Development Server because it would return
http://localhost:12345/{myrequest}
However, when pushed to IIS, and setting my project properties to use Custom Web Server with a value of this:
http://www.mydomain.com/
This is now showing a URL like the following in my RequestContext:
http://{machinename}/{myrequest}
Instead of:
http://www.mydomain.com/{myrequest}
Is this an IIS setting? To get around this, I am forced to modify the URI instance to swap out the machine name with the domain name. This is non-ideal.
Anything I am missing here?

Silverlight -> WCF -> Database -> problem

I have some silverlight code that calls a WCF service which then uses the Entity Framework to access the database and return records.
Everything runs fine but ... when I replace the Entity Framework code with classic ADO.NET code I get an error:
The remote server returned an error: NotFound
When I call the ADO.NET code directly with a unit test it returns records fine so it's not a problem with the ADO.NEt code
I used fiddler and it seems to say that the service cannot be found with a "500" error.
i don't think it's anything to do with the service as the only thing I change is the technology to access the database.
Anyone know what i'm missing here?
'NotFound' is a generic error message that could mean just about anything. If you are absolutely positive that you haven't changed the service interface, then the likely candidate is an exception is being thrown from within your service. Are you sure that the collection type that contains the data you are trying to return hasn't changed, i.e. from List< OfSomthing> to List< OfSomethingElse>?
In any case, something i have found invaluable for tracking this sort of issue is the Service Trace Viewer tool from Microsoft. Read all about it right here, all it takes is some simple changes to your web.config to enable the logging.
John Papa has a great article from MSDN Magazine Data Performance and Fault Strategies in Silverlight 3 that explains this issue and offers a solution. Due to browser limitations, error code 500s aren't routed properly. His solution modifies the outgoing HttpResponse Message back to a 200 for all Silverlight 500 responses.
If you are still stuck, you may want to try making the call to the service from the machine hosting the service. IIS by default returns much more information about what might have gone wrong when the call is from the local machine. (I believe this can be changed, but don't know for sure.)
try to add
HttpWebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
to the Application startup event of the Silverlight app.
It should give you detail of what the real error is rather than NotFound. In my case, i was missing the clientaccesspolicy.xml resuired for cross domain requests.
How to: Specify Browser or Client HTTP Handling

Categories

Resources