Before I ask my question I have already gone through the following posts:
Can't get the OWIN Startup class to run in IIS Express after
renaming ASP.NET project
file and all the posts mentioned in the question.
OWIN Startup Detection
OwinStartupAttribute required in web.config to correct Server Error #884
OWIN Startup class not
detected
Here is my project's folder layout:
Currently there is no controller or view. Just the Owin Startup file.
Startup.cs
using System;
using Microsoft.Owin;
using Owin;
[assembly: OwinStartup(typeof(Bootstrapper.Startup))]
namespace Bootstrapper
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync(GetTime() + " My First OWIN App");
});
}
string GetTime()
{
return DateTime.Now.Millisecond.ToString();
}
}
}
Web.config
<appSettings>
<add key="owin:AutomaticAppStartup" value="true" />
<add key="owin:appStartup" value="Bootstrapper.Startup" />
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
I have the following reference in the Bootstrapper project:
Microsoft.Owin
Microsoft.Owin.Host.SystemWeb
Owin
System
System.Core
UPDATE:
Forgot to add the error message:
Now,
WHY is it not working?
What is the step-by-step process of adding and using an Owin
Startup class in a very basic project(like accessing Home/Index)?
How and when does Configuration method in Owin Startup class is
called/executed?
UPDATE: on 10-Dec-2016
Check the Project-Folder-Layout. In Bootstrapper project I have the following file:
IocConfig.cs
[assembly: PreApplicationStartMethod(typeof(IocConfig), "RegisterDependencies")]
namespace Bootstrapper
{
public class IocConfig
{
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
builder.RegisterModule<AutofacWebTypesModule>();
builder.RegisterType(typeof(MovieService)).As(typeof(IMovieService)).InstancePerRequest();
builder.RegisterType(typeof(MovieRepository)).As(typeof(IMovieRepository)).InstancePerRequest();
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
}
Now I want to execute IocConfig.RegisterDependencies() in OWIN Startup class. I am doing using Bootstrapper in Startup at the top but, it is not working. I mean I am unable to reference IocConfig in Startup. How to resolve this?
Create an empty web application project
Install the OWIN using NuGet (install-package Microsoft.Owin.Host.SystemWeb)
Add an empty class into the project root called "Startup.cs"
Here I will answer your third question. The startup class is an entry point of OWIN and is being looked up automatically. As stated in official docs:
Naming Convention: Katana looks for a class named Startup in namespace
matching the assembly name or the global namespace.
Note, that you can also choose your own name of Startup class but you have to set this up using decorators or AppConfig. As stated here:
https://www.asp.net/aspnet/overview/owin-and-katana/owin-startup-class-detection
This is everything you need for a basic and working OWIN test:
using Owin;
using System;
namespace OwinTest
{
public class Startup
{
public static void Configuration(IAppBuilder app)
{
app.Use(async (ctx, next) =>
{
await ctx.Response.WriteAsync(DateTime.Now.ToString() + " My First OWIN App");
});
}
}
}
If you wish to use MVC (I guess by "Home/Index" you mean MVC), follow these steps:
Install MVC NuGet (install-package Microsoft.AspNet.Mvc).
Add a "Controllers" folder into your project.
Create a new empty controller under the new "Controlles" folder (right click -> add -> MVC 5 Controller - Empty) and name it "HomeController".
Create a view page under newly created "Views/Home" folder. Right click -> add -> View. Name it "Index" and uncheck the "use layour page".
Make the page inherit from WebViewPage. It should all look like this:
#inherits System.Web.Mvc.WebViewPage
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
<h1>Owin Hello</h1>
</div>
</body>
</html>
Add a global.asax to set up routes. Right click on the project -> add -> New Item -> Global Application Class.
Add the routes definition to the Application_Start method:
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.MapRoute(name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index" });
}
Do not forget to comment out the above "..await ctx.Response.WriteAsync..." middleware. It would interfere with the MVC otherwise.
Run the project. Should be working.
It's a little bit late, but I found the solution how to put OWIN Startup class in separate project. Everything you did in your project is correct, you must only apply one change in the properties of your Bootstrapper project. Right click on Bootstrapper project, enter properties, click Build tab and look for Output path. You should see standard output path bin\debug\ which means that your Bootstrapper dll will land in this folder. You must change this to the bin folder, where your whole web app is.
For example, I've created a simple solution with two projects, first is an empty web app, and the second is a library with an OWIN Startup class. In properties of the second project I've changed the output path to ..\OwinTest.Web\bin. This will cause all dlls to land in one folder after the build. You can now run your app and OWIN Startup should work right.
Below is the screen of properties settings of Bootstrapper project:
Three years later, but this might help someone.
The question you ask in your title is answered here:
WebApp.Start Method Type Parameter
The WebApp class uses reflection to get a pointer to the Configuration(IAppBuilder) method then calls it. If the class you provide as the generic type argument does not have a Configuration method with the expected arguments then you get an error at run time.
Related
I have been trying to add Azure application insights to a few projects. The whole experience was seamless with a .net core app. However, when I tried to update the Cloud role name property, that is where I could not find a lot for an OWIN based app. I want the name of the bubble in Insights Application Map to appear what I set in this property (My API for example) but it keeps resorting to the resource name that I have for this resource in Azure (my-azure-api). After scouring through most online resources, I was able to do the following which does not work.
using Microsoft.ApplicationInsights.Channel;
using Microsoft.ApplicationInsights.Extensibility;
namespace MyApp.Insights
{
public class RoleNameInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
// set role name correctly here.
telemetry.Context.Cloud.RoleName = "My API";
}
}
}
Also added the following in the applicationinsights.config
<Add Type="MyApp.Insights.RoleNameInitializer, MyApp"/>
Added the following to the startup class too (Just as a precaution)
using IntegratedTeleHealthPlatformApi.Insights;
using Microsoft.ApplicationInsights.Extensibility;
using Owin;
namespace MyApp
{
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
TelemetryConfiguration
.Active
.TelemetryInitializers
.Add(new RoleNameInitializer());
ConfigureAuth(app);
ApplyDatabaseMigrations();
}
}
}
I just setup a simple owin based asp.net project(asp.net web application, then in nuget install Microsoft.Owin.Host.SystemWeb).
After the setup, in visual studio -> Project -> Add Application Insights Telemetry:
My custom TelemetryInitializer as below:
Then just add the initializer to the applicationinsights.config:
And after execution, the role name is the one which I set in the initializer:
Please have a try if it's ok at your side. And to make sure your RoleNameInitializer is called, you can set breakpoint there to see if it's called or not.
I'm trying to integrate Signalr into my web form project.
First, added the references using nugget
Microsoft.AspNet.SignalR.Client;
Microsoft.AspNet.SignalR.Core;
Microsoft.AspNet.SignalR.System.Web;
Microsoft.Owin;
Microsoft.Owin.Host.SystemWeb;
Microsoft.Owin.Security;
Owin
My startup class:
[assembly: OwinStartup(typeof(ns.App_Code.Startup))]
namespace ns
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
}
My hub:
public class PositionHub : Hub
{
static ConcurrentDictionary<int, List<string>> connectedUsers = new ConcurrentDictionary<int, List<string>>();
public override Task OnConnected()
{
return base.OnConnected();
}
}
Finally, the client-side:
<script type="text/javascript" src="Scripts/jquery-2.2.4.min.js"></script>
<script src="Scripts/jquery.signalR-2.3.0.min.js"></script>
<script src="<%= ResolveUrl("~/signalr/hubs") %>" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
var logger = $.connection.positionHub;
logger.start();
});
</script>
Also, added to web.config the following:
<add key="owin:AutomaticAppStartup" value="true" />
and
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" />
When I run the app it gives the 404 error:
GET http://localhost:41363/signalr/hubs 404 (Not Found)
This is not my first time using signalr, but it is the first time I have this issue, and been struggling for hours to solve it, with no luck...
I notice you don't have the following NuGet packages installed which are required when integrating SignalR with Javascript.
Microsoft.AspNet.SignalR
This package pulls in the server components and JavaScript client required to use SignalR in an ASP.NET application.
Microsoft.AspNet.SignalR.JS
Script client for ASP.NET SignalR.
(This one is included automatically by Microsoft.AspNet.SignalR above.)
EDIT
Via the comments below we found out that OP's web.configfile contained some url rewrite rules which intercepted the /signalr/hubs url.
Adding a rule to prevent this url from being rewritten solved the problem.
<rule name="signalR" enabled="true" stopProcessing="true">
<match url="^signalr.*" /> <action type="None" />
</rule>
fix startup class namespace
namespace ns
to be
namespace TeltonikaSiteWebApplication.App_Code
The rewrite rule was conflicting it on web config was conflicting with signalr. I needed to add a new one to make it work. . Thanks to #pfx on the guidance.
I come with a problem caused by the poor sitecore documentation and my small experience.
The case:
I have a sitecore project which was not set up by me, but I had to develop over it. It's nothing complicated, few renderings - basic stuff
Issue:
I have to add 3 custom routes to use them with some ajax calls. I have the routeconfig.cs file and I added those routes here, but it looks like this is not executed because there is no Global Class anywhere.
So, because I read that I should use those pipelines but I don't exactly understand how to use one that's executed only once, when the app starts
I have one developed by someone else which handles the 404, but this one is executed on each request. I don't want to check if the route exists and register it on this process
Is there any other way ?
This is how it works now:
namespace SS.Configuration.Pipelines
{
public class Custom404ResolverPipeline : HttpRequestProcessor
{
public override void Process(HttpRequestArgs args)
{
Assert.ArgumentNotNull(args, "args");
if (RouteTable.Routes["AjaxCall"] == null) RouteConfig.RegisterRoutes(RouteTable.Routes);
//do some other stuff
You should register your routes in the initialize pipeline so that they are only registered once on application start up: How to register custom ASP.NET MVC routes in Sitecore
Example from the linked article:
Create a custom processor for the initialize pipeline and define custom route in the Process method similar to the following:
public class RegisterCustomRoute
{
public virtual void Process(PipelineArgs args)
{
RouteTable.Routes.MapRoute("CustomRoute", "some/route/{controller}/{action}/{id}");
}
}
Add this processor to the initialize pipeline right before the Sitecore InitializeRoutes processor. You can do this with the help of the configuration patch file in the following way:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<initialize>
<processor type="MyNamespace.RegisterCustomRoute, MyAssembly" patch:before="processor[#type='Sitecore.Mvc.Pipelines.Loader.InitializeRoutes, Sitecore.Mvc']" />
</initialize>
</pipelines>
</sitecore>
</configuration>
If you dont want to go by pipelines way, you can also download web activator package from Nuget and then implement kind of Startup Class to Register your routes.
[assembly: PostApplicationStartMethod(typeof(SomeNameSpace.StartUp), "Start")]
namespace SomeNameSpace
{
public static class StartUp
{
public static void Start()
{
MvcHandler.DisableMvcResponseHeader = true;
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
}
and in your Register routes method of RouteConfig class you can map your route as below
RouteTable.Routes.MapRoute("CustomRoute", "some/route/{controller}/{action}/{id}");
When trying to access the hangfire dashboard on my local IIS at domain/hangfire/ I get a 404 response. This is in a webforms project targeting .Net 4.5.1, Hangfire is version 1.5.3. My startup and authorisationoverride classes are as follows:
[assembly: OwinStartup(typeof(MyNamespace.Startup))]
namespace MyNamespace
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
GlobalConfiguration.Configuration.UseSqlServerStorage("MyConnString");
DashboardOptions opts = new DashboardOptions
{
AuthorizationFilters = new[] { new AuthorisationOverride() }
};
app.UseHangfireServer();
app.UseHangfireDashboard("/hangfire", opts);
}
}
}
public class AuthorisationOverride : Hangfire.Dashboard.IAuthorizationFilter
{
public bool Authorize(IDictionary<string, object> owinEnvironment)
{
return true;
}
}
Jobs are running successfully, but I've run out of ideas for getting the Dashboard to work.
I had something similar but I managed to get it resolved by reading through this post.
Hope you will have a better luck following through that if you haven't yet. The main problem for me was the missing DLL, and then the removing site data from the TemporaryASP.NET folder.
Edit: Someone down voted this answer because I used a link for the solution.
Since I did find a solution to this specific problem, I thought I will give it another try to share. :)
Here are the steps that I have taken to come to a solution.
Confirm you have the Microsoft.Owin.Host.SystemWeb.dll in your bin directory of this project. (In my case, the dll was missing)
Stop your app pool
Navigate to your TemporaryASP.NET folder : C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files and delete the folder inside of your site/application's folder.
Restart you app pool
Navigate to "/admin" or whatever you set your dashboard url to be "/hangfire" by default.
Struggled with this for a few hours today and just fixed it in my project.
Try moving your Hangfire configuration code higher up in your Startup class's Configuration method.
I had my Hangfire configuration code at the very bottom of Startup.Configuration and just happened to discover that the dashboard works again when I move it before some of the other OWIN stuff I was configuring.
Specifically, I moved it above the following code in my project:
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
RouteConfig.RegisterRoutes(RouteTable.Routes);
// my AutoMapper configuration
// some async/await code that was calling .Wait() here.
I didn't take time to figure out exactly which line of code was breaking the Hangfire dashboard, but I hope that helps someone.
Also for the record, the old code was working under IIS Express at https://localhost:44342/hangfire. I was getting the 404 in full IIS at https://localhost/appname/hangfire.
Add this line in your web.config file:
<system.webServer>
<handlers>
<add name="hangfireDashboard" path="hangfire" type="System.Web.DefaultHttpHandler" verb="*" />
</handlers>
</system.webServer>
Since there is no solution so far, I would like to share something that I rectified to get this issue resolved.
If you're facing this issue only in production then, your web.config file is not properly configured.
Firstly, assuming you have already created the Startup class, add the following to the web.config under :
<add key="owin:AutomaticAppStartup" value="true" />
Next, make sure that you have referenced the OWIN assemblies as the below following:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Although, when you install OWIN via nuget, the setup will automatically update the web.config for you, but just in case it doesn't, you can always add this. Further make sure this above OWIN version matches with the one yo have installed via nuget.
Hope this helps somebody!
Edit: Answering the OP's original question, Hangfire returns 404 error when it is not started. Apart from adding the Startup OWIN class, we need to mention automaticstartup=true in the web config also. The next issue IIS will look for is reference to Hangfire, where is we kick in the assembly details.
application Startup
[assembly: OwinStartupAttribute(typeof(yournamespace.Startup))]
namespace yournamespace
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var storage = new SqlServerStorage("connectionstring");
......
......
app.UseHangfireDashboard("/Scheduler", new DashboardOptions() { AuthorizationFilters = new[] { new HangFireAuthorizationFilter() } }, storage);
}
Authorization Filter
public class HangFireAuthorizationFilter:IAuthorizationFilter
{
public bool Authorize(IDictionary<string, object> owinEnvironment)
{
// In case you need an OWIN context, use the next line.
// `OwinContext` class is defined in the `Microsoft.Owin` package.
var context = new OwinContext(owinEnvironment);
return context.Authentication.User.Identity.IsAuthenticated &&
context.Authentication.User.IsInRole("xyz");
}
}
You Can Ignore the HangFireAuthorizationFilter if you want to.
The problem for me was missing ASP.NET installation on the server
My Question Is This
What configuration step have I missed to make Mvc Surface Controllers work in Umbraco?
My theory is that since there is a folder in the default Umbraco install called /umbraco/ which is used to connect to the CMS that the physical path is interfiering with the route /umbraco/surface/{Controller}/{Action} thus resulting in the ASP.NET YSOD (and an IIS 404
when I try to access a controller on that route that isn't defined.)
Background Information
I have added this class to my App_Code folder in a freshly downloaded copy of Umbraco 6.1.6:
public class MembersController : SurfaceController
{
public ActionResult Index()
{
return Content("Hello, Member!");
}
}
When I navigate to what I think should be the route for my Index() method, I get a YSOD that says the resource could not be found:
the code is not executed and the above error is displayed; however, if I change the Uri to garbage I get an IIS 404 error:
I started getting this in an existing site, thinking my site was screwed up I tried it in a new copy of Umbraco 6.1.6 and got the exact same results.
For the record, I have also tried MembersSurfaceController and its associated Uri, which has the exact same result as above. YSOD when I hit the valid route, and IIS 404 when I don't.
I have changed my umbracoSettings.config to MVC in the /config/ directory as well.
update
I'm using the out-of-the-box web.config file, which has this:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="UrlRewriteModule" />
<add name="UrlRewriteModule" type="UrlRewritingNet.Web.UrlRewriteModule, UrlRewritingNet.UrlRewriter" />
.
..
...
On my default Umbraco site I don't have any rewrite rules defined; but on my actual site I have several rewrite rules in place. I'm thinking that's not causing it since I'm seeing the same behavior on both sites though...
I have tried removing UrlRewrite completely I get the same results.
The following approach works for me in Umbraco 7.1, and I expect it to work in 6.1 as well:
Create folder called 'Controllers' within your App_Code folder, and put your surface controllers in there (so that they will be within the 'Controllers' namespace).
E.g. I have the following controller in the App_Code\Controllers folder (and hence, within the 'Controllers' namespace):
namespace Controllers
{
public class ServiceCentersController : SurfaceController
{
public ActionResult GetServiceCenters(string country = "", string region = "", string city = "")
{
...
}
}
}
My site runs on localhost, so I can invoke the GetServiceCenters action by navigating to:
http://localhost/umbraco/Surface/ServiceCenters/GetServiceCenters?country=aa®ion=bb&city=cc
You need a namespace for your controller - the code posted above doesn't have any namespace:
public class MembersController : SurfaceController
{
public ActionResult Index()
{
return Content("Hello, Member!");
}
}
That is why making a namespace of Controllers works ... but you could make this any logically named namespace you want.