running express.js app in Asp.net MVC - asp.net-mvc

I would like to run node.js with asp.net mvc for performing socket.io operations.
i've successfully included the node.js in asp.net mvc as described in here
my problem is how to run express.js in asp.net mvc,
i've performed the url rewritting in Global.asax.cs file like
void Application_BeginRequest(object sender, EventArgs e)
{
// Get current path
string CurrentPath = Request.Path.ToLower();
if (CurrentPath.StartsWith("/node"))
{ HttpContext MyContext = HttpContext.Current;
MyContext.RewritePath("/Node/index.js/");
}
}
so in the url http:localhost:1234/node should redirect me to the index.js file in Node folder
it is all working well but,
when i start coading express.js server in index.js like
var express = require('express');
var app = express.createServer();
app.get('/node/', function (req, res) {
res.send(' welcome to express ');
});
app.listen(process.env.PORT);
I got error saying Cannot GET /Node/index.js/
where am i missing? please guide me how to write express.js coading in asp.net mvc
Iam running this application in windows 7 32 bit system with IIS 8.0 express , and installed node versions are
iisnode.js - iisnode-full-iis7-v0.2.3-x86
node.js - node-v0.8.19-x86
Thank you.

Do you have a web.config entry for iisnode handling index.js?
iisnode is not set up as a .js handler by default, since there is far more client-side javascript than server-side javascript, so you need to explicitly turn on iisnode as a handler for that file.

Related

Configure Autofac to work with ASP.NET MVC and ASP.NET Web Api for an existing application

We have an existing application which has been configured to use AutoFac with ASP.Net MVC:
1) All the controllers, action info and routings have been registered manually using AutoFac
2) Controllers are resolved with an implementation of IControllerFactory's (AutoFacControllerFactory) CreateController() method
3) I have added a new API controller to the existing application
4) Web API routings have been added before any traditional ASP.Net routings as follows:
GlobalConfiguration.Configuration.Routes.MapHttpRoute("GetNetworkFeatures",
"secure/banking/administration/GetNetworkFeatures/Get",
new { controller = "GetNetworkFeatures" });
5) New API controllers have been registered using AutoFac as well before containerBuilder.Build() si called as follows:
foreach (var module in modules)
{
builder.RegisterApiControllers(module);
}
container = containerBuilder.Build();
GetNetworkFeaturesController is loaded in one of the above modules
6) Both dependency resolvers have been registered as follows:
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
7) .Net version is 4.5.2, we are using ASP.Net MVC version 3, AutoFac version is 2.6.3.862, AutoFac.Integration.MVC version is 2.6.3.862, AutoFac.Integration.WebApi version is
2.6.3.863, and Newtonsoft.Json version is 11.0.0.0, IIS server version is 6.1 in Windows Server 2008
8) The target is to make Autofac, Asp.net MVC routing and Web API routing coexist in the same application pool, when I try web API endpoint
http://localhost:7070/secure/banking/administration/GetNetworkFeatures/Get, it still goes to AutoFacControllerFactory's CreateController() method, instead of routing to Get() method of Web API controller GetNetworkFeaturesController
9) I think this may be related to , so I have changed it to true, but the problem still persists. Basically it looks like
configured Web API routing is not respected, although it has no compilation and build errors, if I removed the following default route, it starts to throw HTTP 403 error:
RouteTable.Routes.MapRoute("Default", "{*url}", new { controller = "Unspecified", action = "Unspecified" });
10) The following threads have been referenced:
https://stackoverflow.com/questions/11484904/is-it-possible-to-configure-autofac-to-work-with-asp-net-mvc-and-asp-net-web-api
https://stackoverflow.com/questions/37069666/autofac-with-web-api-controller
https://stackoverflow.com/questions/44986001/web-api-route-values-is-empty-on-action-executes-filter
https://stackoverflow.com/questions/15556035/all-asp-net-web-api-controllers-return-404
https://www.aspforums.net/Threads/218940/Solved-URL-Routing-not-working-with-Web-API-in-IIS-server-and-ASPNet-MVC/
I have fixed up the issue. The reason is we are using a reverse proxy to do the authentication, which is configured to route any authenticated requests of "~/secure/banking/api/XXX" to the real endpoint "api/xxx" in IIS server. If I get rid of the "secure/banking" in the following route template, Web API routing will be respected immediately:
GlobalConfiguration.Configuration.Routes.MapHttpRoute("GetNetworkFeatures",
"secure/banking/administration/GetNetworkFeatures/Get",
new { controller = "GetNetworkFeatures" });
Cheers
William Feng

ASP .NET MVC websocket client to save data in DB

I am struggling to achieve the following:
I have created a Java websocket server which publishes data every 1 sec.
In ASP MVC projest I would like to receive the data and save them in database only so no JS involved here.
I am able to read the websocket data using console application method below :
using WebSocketSharp;
List<string> readoutList = new List<string>();
public void receiveMessage() {
using (var ws = new WebSocket("ws://localhost:4567/socket/"))
{
ws.OnMessage += (sender, e) =>
{
if (e.IsText)
{
readoutList.Add(e.Data.ToString());
Console.WriteLine(e.Data.ToString());
}
};
ws.Connect();
Console.ReadKey(true);
}
}`
How to create a service of this kind within the ASP MVC project? I need some direction here.
MVC is stateless so you have to request back to the server to initiate the request (such as from a form post) but within the MVC controller response, you can kick off the request to the server (as an example using a different technology). The problem is there isn't necessarily a 1 to 1 translation in MVC; initiating the request using client-side JavaSvcript would be the option here. Initiating these types of requests within MVC may cause issues with timeouts too that you have to be aware of.
OR, you can consider a scheduled windows program or a windows service that is installed, which can manage itself and initiate the request every so often. I think this is the better option.

Azure RoleEnvironment.Changing event not being called in ASP.NET MVC 5

I am trying to use the Azure Runtime Reconfiguration Pattern to allow me to change a appSetting in the normal Web.config file via PowerShell (later by Microsoft Azure Web Sites Management Library).
My problem is that the RoleEnvironment.Changing event is not being called in my MVC app, so the web app is being restarted. I have placed event set up code in the MVC Application_Start as described in the Azure article, i.e.
protected void Application_Start()
{
RoleEnvironment.Changing += RoleEnvironment_Changing;
RoleEnvironment.Changed += RoleEnvironment_Changed;
//normal MVC code etc...
AreaRegistration.RegisterAllAreas();
}
The event handlers are a straight copy of the handled from the Azure article and look like this:
private const string CustomSettingName = "TestConfig";
public static string TestConfigValue;
private static void RoleEnvironment_Changing(object sender,
RoleEnvironmentChangingEventArgs e)
{
RoleLogs.Add("RoleEnvironment_Changing: started");
var changedSettings = e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>()
.Select(c => c.ConfigurationSettingName).ToList();
Trace.TraceInformation("Changing notification. Settings being changed: "
+ string.Join(", ", changedSettings));
if (changedSettings
.Any(settingName => !string.Equals(settingName, CustomSettingName,
StringComparison.Ordinal)))
{
Console.WriteLine("Cancelling dynamic configuration change (restarting).");
RoleLogs.Add("RoleEnvironment_Changing: restarting!");
// Setting this to true will restart the role gracefully. If Cancel is not
// set to true, and the change is not handled by the application, the
// application will not use the new value until it is restarted (either
// manually or for some other reason).
e.Cancel = true;
}
else
{
RoleLogs.Add("RoleEnvironment_Changing: change is OK. Not restarting");
Console.WriteLine("Handling configuration change without restarting. ");
}
}
private static void RoleEnvironment_Changed(object sender,
RoleEnvironmentChangedEventArgs e)
{
RoleLogs.Add("RoleEnvironment_ChangED: Starting");
Console.WriteLine("Updating instance with new configuration settings.");
foreach (var settingChange in
e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>())
{
if (string.Equals(settingChange.ConfigurationSettingName,
CustomSettingName,
StringComparison.Ordinal))
{
// Execute a function to update the configuration of the component.
RoleLogs.Add("RoleEnvironment_ChangED: TestConfig has changed");
Console.WriteLine("TestConfig has changed.");
TestConfigValue = RoleEnvironment.GetConfigurationSettingValue(CustomSettingName);
}
}
}
I have added logs which prove that my RoleEnvironment_Changing and RoleEnvironment_Changed are not being called in the MVC WebApp which means the WebApp is restarted when I change an appSetting via PowerShell. This also means the RoleEnvironment.Changing event never gets to the WebJob.
I am using Azure SDK 2.7.0
Any ideas?
UPDATE
#richag gave me an answer, which made me realise that my problem is because I am using a App Service rather than a Cloud Service. This SO answer and plus this video (see at 5:00mins) talks about the difference (Note: the video is old so the name of the web app is different, but the concept is the same).
I don't really want to change this late in the development, and I have worked round the problem another way. Maybe on the next project and will look at Cloud Services as I can see some positives, like better control of my WebJobs configuration.
From the runtime reconfiguration pattern: "Microsoft Azure Cloud Services roles detect and expose two events that are raised when the hosting environment detects a change to the ServiceConfiguration.cscfg files" These events are not fired if you make changes to app.config/web.config files. Only when the cloud service configuration is changed, i.e. if you upload a new configuration file through the azure portal's configure tab or change a setting directly on the azure portal.
According to the debugger, none of the following events are fired when I update the Azure Portal to change an AppSetting for an ASP.NET WebAPI app:
RoleEnvironment.Changing
RoleEnvironment.Changed
RoleEnvironment.StatusCheck
RoleEnvironment.SimultaneousChanging
RoleEnvironment.SimultaneousChanged
RoleEnvironment.Stopping
Do others have different experience?

Project subdirectory as root for static files

New to ASP.NET MVC, I am creating a web application using the Visual Studio 2013 wizard. It creates several folders from where static files are served: Content, Scripts, etc.
Frameworks in other languages (e.g. TurboGears) have an explicit directory only for static content, removing the risk of serving the source code of a page instead of processing it which is a typical configuration mistake of PHP sites.
ASP.NET however is happy to deliver anything in the application's root directory, e.g. http://localhost:1740/Project_Readme.html as long as it has the right extension. Only the Views folder is protected with a Web.config.
How do I configure the application to use another directory than the project's root directory for static files. E.g. if the file favicon.ico is put into the subdirectory Content, it should be accessible as http://localhost:1740/favicon.ico, but nothing outside of the Content directory unless returned by a controller.
Nothing should ever be executed in this directory, that is, if *.cshtml files are put into this directory, the files' contents (the source code) should be delivered as text/plain.
Final application will run using mod_mono on Linux.
Update:
Ben,
The proposed solution works only with Owin. To get it working in an MVC application you have to use asp.net MVC 6 (part of asp.net core or asp.net 5) only. But, with Web API you can use the older versions too. To setup the application please use the following steps:
Create an empty project using visual studio templates(don't select Web API or MVC)
Add the following Nuget packages to the project:
Microsoft.AspNet.WebApi
Microsoft.AspNet.WebApi.Owin
Microsoft.Owin.Host.SystemWeb
Microsoft.Owin.StaticFiles
Add a Startup.cs file and decorate the namespace with the following
[assembly: OwinStartup(typeof(Startup))]
Add the following code to the Stratup.cs class
public void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new {id = RouteParameter.Optional}
);
//Configure the file/ static file serving middleware
var physicalFileSystem = new PhysicalFileSystem(#".\client");
var fileServerOptions = new FileServerOptions
{
EnableDefaultFiles = true,
RequestPath = PathString.Empty,
FileSystem = physicalFileSystem
};
fileServerOptions.DefaultFilesOptions.DefaultFileNames = new[] {"index.html"};
fileServerOptions.StaticFileOptions.ServeUnknownFileTypes = true;
fileServerOptions.StaticFileOptions.FileSystem = physicalFileSystem;
app.UseFileServer(fileServerOptions);
app.UseWebApi(config);
}
This should do the magic. Now you can host the application in IIS. IIS will serve the static assets only from client folder. Add Server folder and add controllers.
The Microsoft.Owin.Host.SystemWeb is what facilitates the hosting of Owin application in IIS. The file serve options help IIS to serve static files only from client folder.
Please let me know if you have any questions.
Based on your question, the project structure that you want to achieve should be like the following.
Basically you will have two folders only, Client and Server. Static files are served from client folder only. Server folder is not accessible. If this is what you need then it can be achieved easily with Owin Self Host with Static File Serving middleware.
Self host works with out any dependency on IIS. But, if your planning to host this application on Linux, you could use Asp.NET CORE 1.0. Later if you decide to host the application on IIS inside windows that can be achieved easily by adding the Microsot.Owin.Host.SystemWeb nuget package.
There are great blog posts on this topic. This is the link for one of them. Here is the link for achieving the same in Asp.NET Core.
I hope this solves your issues and please let me know if you have any questions.
Thank you,
Soma.
The best solution I found is to ignore asp.net normal way and write a new way
public override void Init()
{
BeginRequest -= OnBeginRequest;
BeginRequest += OnBeginRequest;
}
protected void OnBeginRequest(object sender, EventArgs e)
{
if (Request.Url.AbsolutePath.StartsWith("/endPoint"))
{
Context.RemapHandler(endPoint);
}
else
{
Context.RemapHandler(staticHandler);
}
}
Let endPoint and staticHandler implement IHttpHandler
it works but every static file moves through c# so there might be a solution with better performance

SignalR 2.0 - 404 in IIS Virtual Directory

I'm having an issue when deploying a very basic MVC5 app running SignalR 2.0.2. Everything works great in my local development environment when I'm running it with IIS Express. When I deploy to IIS, my js receives a 404 error attempting to connect to SignalR.
More specifically, I'm deploying to an application/virtual directory that is running under my Default Web Site. When I publish directly to Default Web Site, everything works successfully so IIS is not the issue.
GET http://myServer/signalr/negotiate?connectionData=%5B%5D&clientProtocol=1.3&_=1395517687175 404 (Not Found)
I'm assuming the 404 is caused by the missing application name. ie: myServer/MyApp/signalr/negotiate...
I've searched a number of posts and SignalR documentation with no luck regarding IIS and Applications/Virtual Directories and SignalR. Below is snippets of code in my app.
Thanks!
JS:
var connection = $.hubConnection();
var proxy = connection.createHubProxy('TestHub');
connection.start()
.done(function () {
console.log('Now connected, connection ID=' + connection.id + ' using transport=' + connection.transport.name);
})
.fail(function () { console.log('Could not connect'); });
Startup.cs:
app.MapSignalR();
Update
By changing the following JS code I was able to 'fix' the issue. The question is, how proper is this?
//var connection = $.hubConnection();
var connection = $.hubConnection("/MyApp/signalr", { useDefaultPath: false });
Your fix seems reasonable.
{ useDefaultPath: false } simply tells SignalR not to append "/signalr" to the url, so you could also create your connection object like this: var connection = $.hubConnection("/MyApp");
Alternatively, if you want to use JS hub proxies generated at /MyApp/signalr/hubs, you can could connect like this:
var proxy = $.connection.testHub;
// Make sure you always wire up client methods before calling start
proxy.client.myClientMethod = function () { /* ... */ };
$.connection.hub.start()
.done(function () { /* ... */ })
.fail(function () { /* ... */ });
http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-javascript-client#genproxy
A solution which will work in dev, and in IIS hosted as application, virtual directory or root is to configure the hub using the page url as its base. This will mean you won't need to hard code the value and negates configuration change for development and deployed scenarios.
var connection = $.hubConnection(document.location.origin + document.location.pathname);

Resources