ASP.NET 5 (vNext) - Using Filters - asp.net

I have an ASP.NET MVC app that I am trying to migrate to MVC 6 (ASP.NET 5). With that in mind, I have some filters that were added using the process described in this SO post. However, with Global.asax being replaced with Startup.cs, I'm not sure where to add my global filters anymore.
In addition, in my filter I have:
public override void OnResultExecuting(ResultExecutingContext context)
{
context.Controller.ViewBag.MyProperty = "[TESTING]";
}
When I run dnx . run now, I get an error that says:
MyFilter.cs(11,22): error CS1061: 'object' does not contain a definition for 'ViewBag' and no extension method 'ViewBag' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
How do I add global filters in ASP.NET 5 (MVC 6)?

To register global filter you can do following:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().Configure<MvcOptions>(options =>
{
options.Filters.Add(new YourCustomFilter());
});
}
in your Startup.cs
Regarding error you're getting, context.Controller has object type and therefore ViewBag property can't be resolved. Cast it to Controller type first:
public override void OnResultExecuting(ResultExecutingContext context)
{
var controller = (Controller) context.Controller;
controller.ViewBag.MyProperty = "[TESTING]";
}

Related

how to get HttpContext.Current.GetOwinContext() in startup

I very read for this problem but i can not fixed this so i think create a new question in this site.
HttpContext.Current.GetOwinContext();
i want get GetOwinContext values with above code . above code there are in my startup.cs
[assembly: OwinStartupAttribute(typeof(OwinTest.Startup))]
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
var c = HttpContext.Current.GetOwinContext();
}
}
and i get this error
//No owin.Environment item was found in the context
but var c = HttpContext.Current.GetOwinContext(); work for me in HomeController fine.!
I just get GetOwinContext in my startup.cs class.
thankfull
You can't do that. The OWIN context does not exist without a request, and the Startup class only runs once for the application, not for each request. Your Startup class should initialize your middleware and your application and the middleware and the application should access the OWIN context when needed.
As mentioned, what you are asking isn't possible. However, depending on your requirements, the following is possible and gives you access within the context of creating object instances. This is something I needed in order to check for whether an instance was already added else where (I have multiple startup classes in different projects).
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
// Ensure we have our "main" access setup
app.CreatePerOwinContext<DataAccessor>(
(options, owinContext) =>
{
// Check that an instance hasn't already been added to
// the OwinContext in another plugin
return owinContext.Get<DataAccessor>() ?? DataAccessor.CreateInstance(options, owinContext);
}
);
}
Within the CreatePerOwinContext we have access to the OwinContext, so we can access it at the point of creating a new type. This might not help everyone as it's a little more specific to a person's needs, but is useful to know.

Push data server to client web app, how to?

(Regarding Web apps, asp.net 5)
I'm new to this stuff, i want to push data from the server to the client. Displaying 'real-time' data on a website. (something like a chat window).
How should i realize this? I've read about SingalR, but most information seems to be outdated? Is this still a good choice?
For example, one of the problems i run into is when i try to add this:
app.MapSignalR();
to my startup.cs
Error CS1061 'IApplicationBuilder' does not contain a definition for 'MapSignalR' and no extension method 'MapSignalR' accepting a first argument of type 'IApplicationBuilder' could be found
Can someone point me in the right direction?
I believe you can do this with a bridge between IAppBuilder and IApplicationBuilder as shown here:
public static IApplicationBuilder UseAppBuilder(this IApplicationBuilder app, Action<IAppBuilder> configure)
{
app.UseOwin(addToPipeline =>
{
addToPipeline(next =>
{
var appBuilder = new AppBuilder();
appBuilder.Properties["builder.DefaultApp"] = next;
configure(appBuilder);
return appBuilder.Build<AppFunc>();
});
});
return app;
}
Which you would then call from startup to start SignalR:
public void Configure(IApplicationBuilder app)
{
app.UseAppBuilder(appBuilder =>
{
appBuilder.MapSignalR();
appBuilder.Run(context =>
{
});
});
}
Some context, excerpted from the link above:
[In ASP.NET 5, now ASP.NET Core 1.0] the Startup class conventions
have been refined. Katana [the previous version] would search for an
assembly that specified the OwinStartup attribute and then fallback
to searching all assemblies for a class named Startup or
AssemblyName.Startup. ASP.NET does not define an attribute and it only
searches the primary application assembly for a type named Startup (in
any namespace). The Configuration(IAppBuilder app) method is now
Configure(IApplicationBuilder app)...
Middleware that can’t remove their IAppBuilder or OwinMiddleware
dependencies can use a modified approach to run in ASP.NET 5. See this
linked sample for an IApplicationBuilder extension that provides an
IAppBuilder for use with Katana v3 based middleware. This extension
creates a new AppBuilder instance and then wraps the OWIN pipeline
builder pattern around it to integrate into ASP.NET 5.

Unable to run my asp.net mvc web application after installing HangFire

I am working on an asp.net MVC-5 web application, and using nuget i installed the hangfire tool:-
Install-Package Hangfire
but when i run my application i got this exception:-
The following errors occurred while attempting to load the app.
- No assembly found containing an OwinStartupAttribute.
- No assembly found containing a Startup or [AssemblyName].Startup class.
To disable OWIN startup discovery, add the appSetting owin:AutomaticAppStartup with a value of "false" in your web.config.
To specify the OWIN startup Assembly, Class, or Method, add the appSetting owin:AppStartup with the fully qualified startup class or configuration method name in your web.config.
second question. if i got the above error fix, how i can call an action method on predefined intervals using hangfire. currently i am defining this inside my glabal.asax as follow:-
static void ScheduleTaskTrigger()
{
HttpRuntime.Cache.Add("ScheduledTaskTrigger",
string.Empty,
null,
Cache.NoAbsoluteExpiration,
TimeSpan.FromMinutes(60)),
CacheItemPriority.NotRemovable,
new CacheItemRemovedCallback(PerformScheduledTasks));
}
static void PerformScheduledTasks(string key, Object value, CacheItemRemovedReason reason)
{
//Your TODO
HomeController h = new HomeController();
var c = h.ScanServer("12345", "allscan");
ScheduleTaskTrigger();
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
ScheduleTaskTrigger();
}
----EDIT----------
now after adding the startup.css class , i defined the following inside my global.asax :-
HomeController h = new HomeController();
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
// ScheduleTaskTrigger();
RecurringJob.AddOrUpdate(() => h.ScanServer("12345","allscan"), Cron.Minutely);
}
mainly to call an action method named "ScanServer" under the Home controller. now the ScanServer is an async task which have the following defenition :-
public async Task<ActionResult> ScanServer(string tokenfromTMS, string FQDN)
{
so my global.asax is raising this error :-
Async methods are not supported. Please make them synchronous before using them in background.
It seems that your OWIN startUp class is missing, So create a class with name Startup:
public class Startup
{
public void Configuration(IAppBuilder app)
{
//..codes
}
}
For your second question, if you want to call a method, for example each hour you can use RecurringJob:
RecurringJob.AddOrUpdate(() => CallMethod(), Cron.Hourly);

No type was found that matches the controller named

UPDATE: I unloaded the project and re-did it again and it worked.
I'm trying to create a WebApi, my build works fine and I get the error message "No type was found that matches the controller named" when I try to go to URI
This is how my webapiconfig looks like,
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
And below is my controller,
public class ClientController : ApiController
{
public List<Client> Get()
{
ICRepository repository = new CRepository(new CContext());
return repository.GetAllClients().ToList();
}
And this is how my global.asax.cs file looks like,
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
}
I'm trying to browse to the url "http://localhost:50662/api/client"
The complete error is as below,
This XML file does not appear to have any style information associated with it. The document tree is shown below.
No HTTP resource was found that matches the request URI 'http://localhost:50662/api/Client'.No type was found that matches the controller named 'Client'.
My question is different from what it's been marked as duplicate of, the question uses just controller which is MVC and mine is "ApiController" and I did read that before creating this. Also, the marked answer there is similar to what I have in here and my problem still exists.
Any help would be highly appreciated. I'm really lost.
I was getting the same error:
Error><Message>No HTTP resource was found that matches the request URI 'http://localhost:53569/api/values'.</Message><MessageDetail>No type was found that matches the controller named 'values'.</MessageDetail></Error>
By default when I created new controller in asp.net web forms application, it was like this:
ValuesController1 : ApiController
I just simply removed "1", and make it:
ValuesController : ApiController
I don't know if it is a bug or whatever, but it works for me.
you are calling WebApiConfig twice.
WebApiConfig.Register(GlobalConfiguration.Configuration);
GlobalConfiguration.Configure(WebApiConfig.Register);
Remove one of them. if you are using Web Api Version >= 2.0, then remove the first one, otherwise remove the second one.
Edit 1
I think your issue may be similar to this Answer
You might be missing some reference libraries, may not be directly related to Your Controller or API, but the way Web Api finds the Controller, is it go through all assemblies referenced by the application and search for types matching a predicate.
Although it isn't the cause of your problem, mine was actually caused by adding a new item of type class through Visual Studios context-menu and not a Controller.
The generated file had the following structure:
class foo
{
}
I extended the class to inherit from ApiController, but forgot to mark it as public
This is the correct version:
public class FooController : ApiController
{
public string Get(string name="Bar")
{
return $"Hello {name}"};
}
}
Right now I am facing a very similar issue. My error message was No type was found that matches the controller named 'odata'. It seems really strange to me, that it seems to be searching for a controller named ODataController or something like that. So I started looking for the real issue. In my case, it was the fact, that I had forgotten to include a public parameterless contructor to the controller class. I added it and the error went away immediately.

Prevent a ASP.NET MVC global filter from being applied on Elmah action

I'm using Elmah for logging exceptions on my MVC application using Alex Beletsky's elmah-mvc NuGet package.
The application registers some global filters, applied on each action called.
Is there a way to prevent some of those filters from being applied when calling the Elmah.Mvc.ElmahController error log page (foo.com/elmah) ?
A test like below works, of course, but I'm looking for a more elegant way that would not involve modifying the filter (nor the source code from Elmah / Elmah MVC). Is it even possible ?
public class FooAttribute : FilterAttribute, IActionFilter
{
// ...
public void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.Controller is ElmahController)
{
return;
}
// do stuff
}
}
I know that attributes can't be added or removed at runtime.
I thought of wrapping the ElmahController in a new one where I could add an exclusion filter, but I'm not sure how (if possible) to change the web.config to reference this wrapper instead of the original controller.
You could register your global filters through a custom IFilterProvider:
public class MyFilterProvider : IFilterProvider
{
public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
if (controllerContext.Controller is ElmahController)
{
return Enumerable.Empty<Filter>();
}
return ... the collection of your global filters
}
}
and in your Application_Start instead of calling:
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
you would call:
FilterProviders.Providers.Add(new MyFilterProvider());

Resources