Custom HttpHandler is never loaded in IIS 10 - http-status-code-404

We're moving a site to a new server, and running into an issue with a custom HTTP Handler. The old server was IIS 6.1, the new server is IIS 10 (Server 2019).
The handler is meant to handle all requests under a certain directory path (which does not physically exist on disc), and retrieve the requested files from Sql Server, where they are stored as bytes. The handler itself is super simple; while I don't think it is relevant, here is the code for the handler, which is located in the App_Code folder.
Public Class GetCaseUpload
Implements IHttpHandler
Public ReadOnly Property IsReusable As Boolean Implements IHttpHandler.IsReusable
Get
Return True
End Get
End Property
Public Sub ProcessRequest(context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim url = context.Request.Url
Dim guid = url.Segments()(url.Segments.Length - 2).Trim("/".ToCharArray())
Dim dbo = GetDbObj()
Dim data = dbo.ExecuteDR(<s>SELECT * FROM dbo.UPLOADS WHERE GUID = <%= dbo.FixString(guid) %></s>)
If data Is Nothing Then
context.Response.ContentType = "text/plain"
context.Response.Write("The requested upload could not be found." & vbCrLf & "GUID: " & guid)
Else
context.Response.ContentType = data("FILETYPE")
context.Response.BinaryWrite(data("FILEBYTES"))
End If
End Sub
End Class
The pipeline is running in integrated mode. Here is the current Handler mapping in system.webServer:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<add name="GetCaseUploadFile" path="*/cases/uploads/*" verb="GET" type="GetCaseUpload" resourceType="Unspecified" preCondition="integratedMode" />
... others removed for brevity ...
</handlers>
</system.webServer>
I just flat-out deleted the handler entries from the old server, and readded it through the Add Managed Handler dialog in the Handler Mappings section of the site in IIS management console, and that is what it created.
Also, since these files are not ones normally handled by IIS (PDF, JPGs, DOCs, etc.), I've tried adding
<modules runAllManagedModulesForAllRequests="true" />
Although it was working on the old server without needing that.
Any time I try to pull up a file from that directory though, it always returns a 404.0 error, and shows that the request was mapped to the Static File handler. I've turned on Failed Request Tracing, and see the logs for the requests, and nowhere in the details does it ever even mention that it loaded my handler. If I search through the raw XML file, the name of my class is not found at all.
Here is the detailed error screen being shown:

You need to put the handler code in web.config file as suggested in the below section:
<handlers>
<add name="MyHandler" verb="*" path="myhandler.api" type="MyAssembly.MyHandlerClass, MyAssembly"/>
</handlers>
If your application pool running in Classic mode, then the handler reference needs to go into the following section:
<system.web>
<httpHandlers>
<add verb="*" path="myhandler.api" type="MyAssembly.MyHandlerClass, MyAssembly"/>
</httpHandlers>
</system.web>
If your application pool running in Integrated pipelined mode, then the handler reference needs to go into the following section:
<system.webServer>
<handlers>
<add name="MyHandler" verb="*" path="myhandler.api" type="MyAssembly.MyHandlerClass, MyAssembly"/>
</handlers>
<system.webServer>
so first check your application pool mode and set the handler code.

I had the same issue. Service that implements IHttpHandler running fine on IIS 6 migrated to IIS 10 and needed to work out the required config tweak in order to overcome migrated service getting 404.
Answer provided by Jalpa Panchal did the trick.

Related

BVN404 gadget showing in local dev, but not EpiServer integration enviornment

I am able to access this gadget in my local dev environment, but not integration, as you can see below:
Local dev:
Integration:
I double checked the BVN settings from here: https://github.com/Geta/404handler#configuration. They are setup like this in my web.config:
<section name="bvn404Handler" type="BVNetwork.NotFound.Configuration.Bvn404HandlerConfiguration, BVNetwork.EPi404" />
<episerver.shell>
<publicModules rootPath="~/modules/" autoDiscovery="Modules" />
<protectedModules rootPath="~/EPiServer/">
<add name="BVNetwork.404Handler" />
<bvn404Handler handlerMode="On">
<providers>
<add name="Custom Handler" type="CompanyName.Business.CustomPageNotFoundHandler, companyname-cms" />
</providers>
</bvn404Handler>
There is not a securedComponents section, though I did try to add one with allowedRoles="Administrator", allowedRoles="*", and allowedRoles="Everyone" for testing purposes.
Any ideas why the gadget can't be viewed when published?
The issue was that the BVN zip file did not publish to the modules folder for some reason. After adding it back, it worked as expected.
Nuget installations sometimes misses the protectedmodules section
Ensure the BVNetwork.404Handler is in your protectedModules collection in web.config. Nuget sometimes miss that.
<episerver.shell>
<protectedModules rootPath="~/EPiServer/"> <!-- this line may vary -->
<!-- other modules -->
<add name="BVNetwork.404Handler" />
</protectedModules>
</episerver.shell>

Error when running a .net core web app with React.js on IIS 10

I have a web app based on .net core v2.1 with a React.js front-end, which I'm trying to host on IIS 10. The app runs fine via Visual Studio (2017), however when I publish the app and host via IIS, I get the following error:
Error image
HTTP Error 500.19 - Internal Server Error
The requested page cannot be accessed because the related configuration data for the page is invalid.
Error Code 0x8007000d
The web.config file was generated during the publish; I have not modified it:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\SkillsMatrix.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
</system.webServer>
</location>
</configuration>
<!--ProjectGuid: ea8a300c-5bb6-4a29-a8d2-d13dddbbac1d-->
This same error happens if I start a brand new project via VS, do not add any code, and publish it to IIS...
I have tried:
Giving access to the folder/file to the IIS_IUSRS user group
Removing app.UseHttpsRedirection(); in StartUp.cs
Does anyone have any suggestions for how I can clear this error and host my app?
You could try the below steps to resolve the issue:
1)Make sure you download and install the .net core hosting bundle and runtime.
https://dotnet.microsoft.com/download/dotnet-core/3.1
2)Make sure that the Application Pool > Process Model > Identity is set to ApplicationPoolIdentity or your custom identity has the correct permissions to access the application's deployment folder.
3)Set the application pool set the .NET CLR version to No Managed Code:
4)Confirm that you have enabled the proper server role. See IIS Configuration.
you could the below link for more detail:
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-3.1

Entity Framework Provider Configuration

I'm using EF 6.1 Code First. I'm programmatically configuring the connection string at runtime like:
myContext.Database.Connection.ConnectionString = "Data Source=(localdb)\v11.0;Initial Catalog=MyDb;Integrated Security=True;"
This works fine, but only if I keep some boiler plate connection information in my app/web.config:
<connectionStrings>
<add name="MyDb" connectionString="Data Source=NOTUSED;Initial Catalog=NOTUSED;" providerName="System.Data.SqlClient" />
</connectionStrings>
I suspect this is because I'm not providing the provider information. I am specifying the provider and defaultConnectionFactory sections (SQL Server / LocalDbConnectionFactory), but it doesn't seem to care:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v11.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
If I remove the connection strings section, it attempts to attach to a mdf file that doesn't exist:
System.Data.SqlClient.SqlException: Cannot attach the file 'C:\My
Project\App_Data\MyDb.mdf' as database MyDb.
Normally, the localdb connection string results in a path to c:\users\my_user\MyDb.mdf. So it seems like it's not using the LocalDb factory unless I've got the connection string section in my .config file.
How can I specify - on a per context basis - the providerName information that EF is getting from that connection string node? Or am I barking up the wrong tree here?
This may have something to do with the way you are constructing your connection. If you are using the default constructor on the DataContext, then it will attempt to find your connection string from the config file:
MyDbContext myContext = new MyDbContext() <- this uses the default constructor
myContext.Database.Connection.ConnectionString = "_conn_str_"
If you pass the connection string in the constructor, then you should not need the config file entry:
using (MyDbContext myContext = new MyDbContext("_conn_str_")) {
// the above line should not need an entry in the config file
}
Hope this helps.

Calling WCF service with forms authentication

I have wpf application that calls wcf service with forms authentication.
I added Service Reference to my solution, and in service configuration checked Generate asynchronous operations.
In code behind I created client to that reference,
than I attached event to fire after async method is completed,
then username and pass is setted:
client.ClientCredentials.UserName.UserName = txtUser.Text;
client.ClientCredentials.UserName.Password = passbox.Password;
client.IsAuthenticatedAsync(txtUser.Text, passbox.Password);
client.Close();
in IsAuthenticatedCompletedEventArgs I get error:
"The communication object, System.ServiceModel.Channels.HttpsChannelFactory+HttpsRequestChannel, cannot be used for communication because it has been Aborted."
Does anyone knows why this happens?
Thanks in advance!
To be honest, I haven't had a chance to test your scenario, but that error is a general error stating something went wrong while communicating with the service (this answer is more of a comment, but it's extensive and can't fit). You could get more info by putting the following lines at the end of the <configuration> section in your web.config and app.config:
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="sdt"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "ServiceTestWCFTrace.svclog" />
</listeners>
</source>
</sources>
After you get the error use svc log viewer to view the log: C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\SvcTraceViewer.exe
There you'll probably find the exact error that caused the Abort on the channel. Hope it helps.

Running MSTest with tests against different databases

I would like to ask what is the best way to execute a setup like the following:
We have tests suite that is compiled, and in the app.config file I have 6-7 different connection strings to different databases. I would like to run the tests suite against every connection, and I hoped to parametrize in some way this process - something like setting the name of the connection and passing it on to the testrun as a parameter. What I figured out so far is that I can use different localconfigrun files and through deployment items I can feed a xml/txt file with the required value, but is there a nicer and lighter solution? I need just to send a key/value pair or simple string to configure my base class inside the test suite.
I am using tfsbuild but I can use the mstest thrugh other environments as well (pure msbuild, etc.)
Thanks in advance.
I have had a similar issue. This is what I did:
My app.config looks like this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="ConenctToInputDB" value="InputDev" />
<add key="ConnectToOutputDB" value ="OutputDev"/>
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
<connectionStrings>
<add name="LocalConnection" connectionString="YOUR CONNECTION STRING HERE" />
<add name="InputDev" connectionString="YOUR CONNECTION STRING HERE" />
<add name="InputCert" connectionString="YOUR CONNECTION STRING HERE"/>
<add name="OutputDev" connectionString="YOUR CONNECTION STRING HERE/>
<add name="OutputCert" connectionString="YOUR CONNECTION STRING HERE" />
<add name="InputProd" connectionString="YOUR CONNECTION STRING HERE/>
<add name="OutputProd" connectionString="YOUR CONNECTION STRING HERE" />
</connectionStrings>
In this secenario, I have 2 dbs I connect to and I have 3 different connection strings for each (Development, Certification and Production)
Add this to the bottom of your project file (right click on the project and unload it). Make sure you add it before the </project> tag. (You will need to install the MSBuild Community Tasks for this to work. They can be downloaded for free from: http://msbuildtasks.tigris.org/ (Make sure you get a nightly build))
<PropertyGroup>
<!--Import the MSBuild community tasks so we can update xml-->
<MSBuildCommunityTasksPath>C:\PathToMSBuildCommunityTasks\MSBuildTasks</MSBuildCommunityTasksPath>
<SubstitutionsFile Condition="'$(Configuration)' == 'Debug'">DevAppSettings.xml</SubstitutionsFile>
<SubstitutionsFile Condition="'$(Configuration)' == 'Cert'">CertAppSettings.xml</SubstitutionsFile>
<SubstitutionsFile Condition="'$(Configuration)' == 'Prod'">ProdAppSettings.xml</SubstitutionsFile>
</PropertyGroup>
<Import Project="C:\PathToMSBuildCommunityTasks\lib\MSBuildTasks\MSBuild.Community.Tasks.Targets" />
<Target Name="AfterBuild">
<!--Update the app config to have the correct environment paths-->
<Message Text="Updating $(MSBuildProjectName) config to $(Configuration)" Importance="high"></Message>
<XmlMassUpdate ContentFile="$(OutDir)\$(MSBuildProjectName).dll.config" SubstitutionsFile="..\..\$(SubstitutionsFile)" />
</Target>
This will replace the <appSettings> section of the app.config file based on the current configuration. You will need to make new new configurations (I called them Cert and Prod).
The last step is to make a file for each configuration (I called them DevAppConfig.xml, CertAppConfig.xml, ProdAppConfig.xml)
In each file should look like this (this one is for the Certification Configuration):
<?xml version="1.0" encoding="utf-8"?>
<!--This file is used by the build files to merge in solution wide app settings
Some projects contain files that have an AppSetting section (usually in App.config). Those projects have
and AfterBuild event in the project file that substitues this xml tree over the the normal xml tree.-->
<configuration xmlns:xmu="urn:msbuildcommunitytasks-xmlmassupdate">
<appSettings>
<add xmu:key="key" key="ConenctToInputDB" value="Cert"/>
<add xmu:key="key" key="ConnectToOutputDB" value="ESPCert"/>
</appSettings>
</configuration>
all of this, once installed will make the file that is output by app.config be auto changed based on the configuration you are compiling. This code works for both compiling in the IDE and in Team Build.

Resources