I have developed a .NET REST web service in C#. While I have plenty of C# experience, I unfortunately do not have much understanding in deploying such a service in a web hosting environment.
Due to the environment, I do NOT have access to IIS.
The advice I have been provided with by the support services of the hosting provider is as follows:
Create a subdomain of the main domain to achieve a dedicated application pool (this a requirement of the host provider)
Create a Bin folder to hold my compiled libraries of source code
Add the following to the Web.Config file:
<system.web>
<httpHandlers>
<add type="ReportRESTWebService.Service, ReportRESTWebService" verb="*" path="report" />
</httpHandlers>
</system.web>
<system.webServer>
<handlers>
<add name="report" path="report" verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" resourceType="File" requireAccess="Script" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
</handlers>
<directoryBrowse enabled="false" />
</system.webServer>
The above would have the effect of creating a handler mapping for the report resource on all HTTP verbs and forwarding any HTTP traffic on that resource to my ReportRESTWebService.dll for handling.
The point I am unclear on is whether the above will be satisfactory and how do I test whether the advice I am given is correct. I know that I have the site running locally but I have access to IIS so I have control over the configuration.
Hopefully somebody can help.
Thanks
If you are using Wcf Rest,then you can probably consider hosting it as as windows service
or self hosted service.
Windows Service
http://blogs.msdn.com/b/juveriak/archive/2009/03/15/rest-endpoint-hosted-in-a-wcf-windows-service.aspx
Self hosted Service
http://www.c-sharpcorner.com/uploadfile/dhananjaycoder/self-hosted-wcf-rest-service-or-hosting-wcf-rest-service-in-console-application/
It would seem, after a day of exhaustive testing, that the steps I had taken (detailed in the question) would be satisfactory.
One point to watch out for is the matching Managed Pipeline Mode for your application pool. Failure to match this up correctly with your Web.Config will result in pain.
Related
We have a frontend running React server off a Node.JS server that is talking to a backend running as a .Net 5 web service.
The services are running fine when placed on two Azure App Service instances, however, we are interested in simplifying deployment by having the two run on the same App Server instance.
Is this possible, or should we just move on?
In our efforts, we have the following web.config cobbled together based on merging different ideas we have found. It is basically serving Node.JS through iisnode whereas the /api-calls are directed to the .Net DLL.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<remove name="aspNetCore"/>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified"/>
<add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<!-- Serve static files directly -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<!-- All calls not going to "/api" or "/apiv2" are sent to server.js -->
<rule name="DynamicContent">
<match url="(api|apiv2)" negate="true" />
<action type="Rewrite" url="server.js"/>
</rule>
</rules>
</rewrite>
<aspNetCore processPath="dotnet" arguments=".\Backend.Api.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess"/>
</system.webServer>
</configuration>
we updated our server.js to the following simple setup to avoid any extra problems;
const express = require('express');
const server = express();
// We need to get the port that IISNode passes into us
// using the PORT environment variable, if it isn't set use a default value
const port = process.env.PORT || 3000;
// Setup a route at the index of our app
server.get('/', (req, res) => {
return res.status(200).send('Hello World');
});
server.listen(port, () => {
console.log(`Listening on ${port}`);
});
In our Azure App Service we are running .Net Stack and .Net 5 major and minor version. We have not Startup command. The App Service Plan is running Linux.
To summarize, the API is working fine, it is the iisnode/Node.JS server that is not working as expected giving 404 errors. We assume the complete Node.JS is not even starting.
Call to the route give error message like so:
{"type":"https://httpstatuses.com/405","title":"Method Not Allowed","status":405,"traceId":"xxx"}
Whereas calls to any other URL than /api /api2 give:
{"type":"https://httpstatuses.com/404","title":"Not Found","status":404,"traceId":"xxx"}
We are not seeing any errors in the server logs.
On Windows OS, IIS enables you to set up many virtual applications inside of a single website if you select the Windows Web App option. To use this strategy, you could follow the Multiple applications deployment in a single azure app service provided by Microsoft.
Note: The same application pool would be shared by the several virtual applications.
Or
It might be CORS in the app.js backend file is not enabled ad that is stopping to access the backend by frontend.
You can try the below steps if it helps to fix the issue:
Set up a separate app service for front-end applications like Angular, React, Node JS and others.
From the frontend application, call the Node JS APIs.
Or,
A gulp file is used to build up and operate the client and server on the same server, and the project is then deployed to an app service. In that situation, no cross-site communication occurs. This is the one that is most favored.
C#, .NetCore 2.2, Visual Studio 2019
I am having a really hard time getting used to the web.config to appsettings.json conversion process. Yes, I have read the docs but there is something I am missing.
I have been told that there is no 1:1 conversion from web.config to appsettings.json. I have read that there is nothing particularly special about the appsettings.json file and that the info there could be in nearly any other format / storage system. I have read that appsettings is just read by whatever policy provider needs to read it.
How do you know what policy providers exist or which one(s) you need?
In ny current case I have an existing, older project that uses a third party web base authentication service called "Siteminder". The use case is very simple: the older app has a small set of controllers. Siteminder is configured (server level not app level) to monitor request URLs. If a request goes to "https://thing.company.com/Auth/" then Siteminder looks for its auth token and either interrupts the request and challenges the visitor for credentials or validates and passes the request on.
My new app should work the same way.
The old app has a web.config that looks something like:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*"
modules="AspNetCoreModuleV2"
resourceType="Unspecified" />
<add name="handler-wa-32" path="*" verb="*"
modules="IsapiModule"
scriptProcessor="C:\Program Files\CA\webagent\win32\bin\ISAPI6WebAgent.dll"
resourceType="Unspecified"
requireAccess="None" preCondition="classicMode,bitness32" />
<add name="CASiteMinderWebAgentHandler-fcc-32"
path="*.fcc" verb="*"
modules="CASiteMinderWebagentModule-32"
resourceType="Unspecified"
preCondition="integratedMode,bitness32" />
<!-- 10 additional, similar "CASiteMinderWebAgentHandler-???-??" handlers !-->
</handlers>
<modules>
<add name="CASiteMinderWebagentModule"
preCondition="integratedMode,bitness64" />
<add name="CASiteMinderWebagentModule-32"
preCondition="integratedMode,bitness32" />
</modules>
<isapiFilters>
<filter name="SiteMinder Agent"
path="C:\Program Files\CA\webagent\win64\bin\ISAPI6WebAgent.dll" enabled="true"
preCondition="classicMode,bitness64" />
<filter name="SiteMinder Agent-32"
path="C:\Program Files\CA\webagent\win32\bin\ISAPI6WebAgent.dll" enabled="true"
preCondition="classicMode,bitness32" />
</isapiFilters>
</system.webServer>
</location>
</configuration>
I have not found Siteminder docs on using .Net Core 2.x yet. I have no idea how to let my app, the web server, whatever, know about these settingS.
It feels like there is a missing section of documentation. How do you port this sort of config over to appsettings and let whatever systems, services, providers know about them?
SiteMinder does not provide plugins for .Net Core. Further, HTTP Modules written for IIS/.Net 4.x are not compatible with .Net Core anyway, which has a very different request processing pipeline.
I've done a fair amount of work with enabling "traditional" access managers to work with .Net Core. Its tricky. (disclaimer, shameless plug here...). My company's product provides a universal REST-based interface for use with SSO products including SiteMinder, and provides .Net and .Net Core libraries (as well as Java, C, C++, and a variety of web and app servers). You might ask your SiteMinder owners to take a look, the link is on my profile.
Looks like my best solution is to continue to use web.config for Siteminder. It works. I was hoping that there was a way around that though.
I published an aps.net core 2.0 mvc app to a shared web hosting server that uses Plesk as control panel. The app works fine. However, I got the following error message when trying to access the web statistics:
This example.com page can’t be found
No webpage was found for the web address: https://example.com/plesk-stat/webstat/
HTTP ERROR 404
I contacted their support and got the answer "the .net core application settings aren't allowing the webstats to load. We recommend you consult with an experienced website developer to customize the web.config code accordingly for the website.", but they don't know how to configure the web.config file.
I really want to make the webstat to work. Any suggestion will be appreciated.
If URL Rewrite is blocking the access, try adding this string to the <conditions> section of the rule which is affecting webstat page:
<add input="{REQUEST_URI}" pattern="^/(plesk-stat/webstat)" negate="true" />
If that does nor help, configure failed request tracing to find which exact module is performing a redirect.
Along with changes in the web.config of the ASP.Net Core site itself to send the /plesk-stat/ url to IIS, a web.config must be added in the following directory:
C:\Inetpub\vhosts\{domain.tld}\.plesk\statistics\{domain.tld}\
(replace {domain.tld} with your domain), with the following contents:
<configuration>
<system.webServer>
<handlers>
<remove name="aspNetCore" />
</handlers>
</system.webServer>
</configuration>
This has to be done by the hosting provider on the server. Maybe you should contact the support of your hosting provider.
I'm looking for a way to pass data to an asp.net core web application as environment variables.
You can do this via IIS via:
Management > Configuration Editor > environment variables > ...
However, that just writes the values into the web.config for the project:
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath=".\Foo.exe" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false">
<environmentVariables>
<environmentVariable name="Foo" value="Bar" />
<environmentVariable name="FooBar" value="1" />
</environmentVariables>
</aspNetCore>
</system.webServer>
That's lovely and all, but unfortunately also quite useless, because if I have three websites, pointing to the same published folder, they now all share the same 'environment' variables.
...
Not really environment variables.
More like appsettings.
I looked into 'application settings' in IIS, but since kestrel runs in its own process, the code for the application instances is not managed code and that doesn't work either (note that using 'No managed code' or '...whatever CLR version here' in the application pool settings is irrelevant for .net core apps).
So, if you have multiple sites configured in IIS for an app, pointing to the same folder, is there any way to pass different configuration to each site instance from IIS?
I believe everything that you change in IIS is saved to the web.config. This is so that as a developer you don't actually have to set up the same configuration on every server the app is deployed to. Unfortunately this means that no, there is no way to do what you are asking.
You will need to publish to three separate folders so you can have three web.config files.
I have a Visual Studio 2010 solution with 2 projects. One is a Silverlight client, the other a web site to which I added a domain service. It works fine when debugging in Cassini, but when I publish to IIS I get nothing returned from my entity query.
I'm not even sure where to start as this is my first attempt at doing this.
A few things:
Developing on Cassini (don't do it if you can avoid it)
It's always better to develop against IIS itself. There are differences between IIS and Cassini which can bite you if you aren't aware of them and it just makes more sense; you should always develop as close to the environment that you are develping for. Unless you are deploying to Cassini (and you aren't, no one does) then there's no point in developing against it unless you simply can't (you don't have a local install of IIS).
Web Deploy
Install Web Deploy on the IIS server you are going to deploy to. Once you do that, you can right click the web/domain project in your solution and select "Build Deployment Package".
Then, you will get a package that you can use with Web Deploy which will deploy everything (Silverlight, ASP.NET components, etc, etc) your project to IIS with a simple command-line call.
This was a very stupid, newbie issue. I used SQL Server Profiler to watch the queries come in and realized the account being used to authenticate against SQL Server was the server's computer account. I secured the Domain Service's methods and allowed the computer account access tot he DB.
Deploying to IIS might have some issues. I'd like to see what errors messages you're getting. Without these information it will become pretty difficult to give you an advice.
PS: I'm gonna assume that your WCF RIA services have valid definition ;-).
Based on my experience, this is the minimum config file, but it certainly will require more settings if you're consuming Authentication Domain Services or Data domain services (such as LinqToEntities or LinqToSql domain services):
Make sure your IIS have all the sections required by WCF RIA
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.serviceModel">
<section name="domainServices" type="System.ServiceModel.DomainServices.Hosting.DomainServicesSection, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" allowDefinition="MachineToApplication" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web>
<!-- You might need identify tag if you app requires additional permission to run -->
<!-- See you want to see more details when a error happens -->
<customErrors mode="Off"/>
<compilation debug="true" targetFramework="4.0" />
<!-- If your application uses authentication and authoriztion then -->
<!-- Elements required required for authentication: authentication and membership and probably roleManager -->
<httpModules>
<add name="DomainServiceModule" type="System.ServiceModel.DomainServices.Hosting.DomainServiceHttpModule, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</httpModules>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<add name="DomainServiceModule" preCondition="managedHandler"
type="System.ServiceModel.DomainServices.Hosting.DomainServiceHttpModule, System.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</modules>
</system.webServer>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>
Make sure the WCF RIA services are up and runnning
Try to access the WCF RIA service by using a web browser. Usually the service you're exposing has format like:
http://[hostname]/[namespacename]-[classname].svc
So, you should be able to hit the URL and see an output like:
Make sure DLLS are available
There are two options to deploy the WCF RIA dlls in the server side. You can indicate to the application that DLLs should be copied into the bin folder of your application or you can run the WCF RIA installer in server mode.
Accessing the services from the client
If the services are up and running they should be reachable to your Silverlight client. If there is an error you can start tracing by enabling WCF RIA debugging.
See http://blogs.msdn.com/b/saurabh/archive/2010/03/16/ria-services-application-deployment.aspx for more details about it.