How to get ApplicationDbContext out of the Owin pipeline - asp.net

This has to be simple, but I'm going bug-eyed trying to find the answer. How does a controller action get a reference to the per-request ApplicationDbContext that was stashed in the Owin pipeline?
EDIT: Ok, I think I'm getting closer... or maybe not... All of my Googling seems to lead to this blog post, which sez to use:
var dbContext = context.Get<ApplicationDbContext>();
where context is apparently an instance of Microsoft.Owin.IOwinContext. So I tried:
var db = HttpContext.GetOwinContext().Get<ApplicationDbContext>();
But the Get<T> method requires a string key parameter. :(

And the answer (apparently) is... You need to add this using statement to get it to work:
using Microsoft.AspNet.Identity.Owin;
so a complete example would look like:
using Microsoft.AspNet.Identity.Owin;
public class HomeController : Controller
{
public ActionResult Index()
{
var context = HttpContext.GetOwinContext().Get<ApplicationDbContext>();
DoSomething(context); // Use the context object; do not dispose it!
return View();
}
}

Related

Unit testing if methods find and return a view in ASP.NET

I'm new to ASP.NET and I'm refactoring some functionalities in my MVC-structured ASP.NET application into area's. This has already lead to controller-methods not able to find their views anymore, which results in the following page:
To test if all controllers can find their views, I'd like to write some automated unit tests for this.
I have came up with the following:
[TestMethod]
public void AboutTest()
{
var controller = new HomeController();
var result = controller.About() as ViewResult;
Assert.IsNotNull(result);
}
which tests the About-method in the following code:
public class HomeController : Controller
{
public ActionResult About()
{
return View();
}
public ActionResult Contact()
{
return View("~/Views/SomeFolder/Contact.cshtml");
}
}
But even when the HomeControllers About-method can not find a view, this assert succeeds, so this does not work for me.
I have found a solution online to use use ViewEngine.FindView() here. I don't think I can use this, since in some controllers the views are referenced by a hardcoded string (see the contact method in the example controller above) instead of just returning the default view (simularly named as its method). The ViewEngine.FindView(controller.ControllerContext, "about", "about"); will then fail, but the controller-method would not.
Another solution states to use Assert.IsEqual() and check if the result.ViewName is equal to a hardcoded string (for example: "About"). Since I do not set or know the title of the views I'm expecting to get returned, this would not be a solution either.
(How) would I be able to test my application for this?
You shouldn't check for null, it will return a ViewResult even when it doesn't render.
To test whether it actually renders use AssertViewRendered from mvccontrib.
[TestMethod]
public void AboutTest()
{
var controller = new HomeController();
var result = controller.About().AssertViewRendered();
}
You can even check for a specific view like so:
result.AssertViewRendered().ForView(MVC.Your.Views.AboutView);
Or supply data like so:
controller.page().AssertViewRendered().ForView("page").WithViewData<SomeModel>();
For an interactive tutorial with lots of pictures I can recommend: http://toreaurstad.blogspot.nl/2011/09/adventures-with-mvccontrib-testhelper.html
Edit:
You might also check out Selenium to test your entire app (incl. rendering of 200 routes).

The operation cannot be completed because the DbContext has been disposed. nopcommerce

I am getting DbContext has been disposed error when I try to get data from database using below code that have mention.
How to solved this issue ?
public class ExampleService<T> where T : Example
{
protected readonly IRepository<T> _exampleRepository;
public ExampleService()
{
_exampleRepository= EngineContext.Current.Resolve<IRepository<T>>();
}
public IList<T> GetService()
{
var query = _exampleRepository.Table;
return query.ToList();
}
}
I think there is not enough code in your sample. It should work perfectly if you're getting ExampleService from the dependency scope.
So my answer is this: Use dependency injection at your constructor instead of using a ResourceLocator. If you declare the dependencies at the constructor instead and still have problems, like for instance, not receiving an instance of IRepository then you can be sure you're instantiating ExampleService the wrong way, outside of the autofac scope, and that is a sure cause for trouble.
The issue is some parts of the object should be disposed, while it still in use.
Try to always resolve the service in this way:
protected readonly IRepository<T> _exampleRepository;
To
var _exampleRepository = EngineContext.Current.Resolve<IRepository<T>>();
Hope this helps!

Unable to utilize UrlHelper

I'm currently trying to do something that was dead simple and straight forward in ASP.NET 4 however this ins't the case now in ASP.NET 5.
Previously to use the UrlHelper it was dead simple:
var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
However I can't for the life of me wrap my head around how to use the new UrlHelper. I'm looking at the test cases and either I'm completely daft or I'm missing something and I can't seem to figure it out. Any help here in clearing up this would be great.
Update - Post RC2
As #deebo mentioned, you no longer can get an IUrlHelper directly from DI. Instead you need to inject an IUrlHelperFactory and an IActionContextAccessor into your class and use them to get the IUrlHelper instance as in:
public MyClass(IUrlHelperFactory urlHelperFactory, IActionContextAccessor actionAccessor)
{
this.urlHelperFactory = urlHelperFactory;
this.actionAccessor = actionAccessor;
}
public void SomeMethod()
{
var urlHelper = this.urlHelperFactory.GetUrlHelper(this.actionAccessor.ActionContext);
}
You need to also register the in your startup class (IUrlHelperFactory is already registered by default):
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
Bear in mind this will only work as long as the code where you get the actionContext is running after the MVC/routing middleware! (Otherwise actionAccessor.ActionContext would be null)
I have retrieved the IUrlHelper using the IServiceProvider in HttpContext.RequestServices.
Usually you will have an HttpContext property at hand:
In a controller action method you can do:
var urlHelper = this.Context.RequestServices.GetRequiredService<IUrlHelper>();
ViewBag.Url = urlHelper.Action("Contact", "Home", new { foo = 1 });
In a filter you can do:
public void OnActionExecuted(ActionExecutedContext context)
{
var urlHelper = context.HttpContext.RequestServices.GetRequiredService<IUrlHelper>();
var actionUrl = urlHelper.Action("Contact", "Home", new { foo = 1 });
//use actionUrl ...
}
Another option would be taking advantage of the built-in dependency injection, for example your controller could have a constructor like the following one and at runtime an IUrlHelper instance will be provided:
private IUrlHelper _urlHelper;
public HomeController(IUrlHelper urlHelper)
{
_urlHelper = urlHelper;
}
Thought I would share for the upcoming RC2 since the current answer won't work anymore then.
From RC 2 you will need to explicitly register IActionContextAccessor and IUrlHelperFactory
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddSingleton<IUrlHelperFactory, UrlHelperFactory>();
Then use the DI/service locator:
public EmailTagHelper(IUrlHelperFactory urlHelperFactory, IActionContextAccessor actionContextAccessor)
{
_urlHelper = urlHelperFactory.GetUrlHelper(actionContextAccessor.ActionContext);
}
I blogged about it here with regard to TagHelpers: http://devonburriss.me/asp-net-5-tips-urlhelper
In Startup.cs
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddSingleton<IUrlHelperFactory, UrlHelperFactory>();
services.AddScoped(it => it.GetService<IUrlHelperFactory>()
.GetUrlHelper(it.GetService<IActionContextAccessor>().ActionContext));
Alternatively
PM> Install-Package AspNetCore.IServiceCollection.AddIUrlHelper
In Startup.cs
services.AddUrlHelper();
If you just need the UrlHelper.Link method like I did, you don't even need the UrlHelper any more, just use Url.Link
A shorter version without constructing special Factory class
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>()
.AddScoped<IUrlHelper>(sp => new UrlHelper(sp.GetRequiredService<IActionContextAccessor>().ActionContext));

Can't use ODataQueryOptions with a (regular - not webapi) Controller derived class?

public class XYZController : Controller
{
public ActionResult Index(ODataQueryOptions<Security> options = null)
{
var xyzs= GetXYZs().AsQueryable();
var results = options == null ? xyzs: options.ApplyTo(xyzs);
return View(xyzs);
}
}
This results in "No parameterless constructor defined for this object" error.
I essentially want to pass odata compliant parameters in to a regular controller.
Can this not be done?
I temporarily (until regular controllers can use ODataQueryOptions) solved this through the use of Linq2Rest (NuGet: install-package Linq2Rest)
This quite powerful library allowed me to accomplish what I am looking for with one line of code:
using Linq2Rest;
public ActionResult Index()
{
var filteredSource = GetXYZs().AsQueryable().Filter(Request.Params);
return View(filteredSource);
}
Now you can hit this Controller's Index Action like this:
xyz.com?$filter=something eq 'foo' and another gt 3&$orderby another
ODataQueryOptions<T> is only supported with web API now. That said, this is an interesting scenario. I have opened this issue on codeplex to track it.

NVelocity extension method ASP.NET webform

I was wondering if it's possible to use an extension method with asp.net webforms and nvelocity. I would like to set some defaults if the string value is null or empty.
Example of .vm file:
Example of my email body...
Billable Status: $billableStatus.Evaluate()
rest of my email body...
Attempted extension method:
public static class Helper
{
public static string Evaluate(this string value)
{
if (String.IsNullOrEmpty(value))
return "Not Provided";
else
return value;
}
}
Or is there an alternative to what I'm tryting to accomplish?
I don't think NVelocity can resolve extension methods with C#/VB.NET syntax sugar. What I do is register an instance of a helper in the velocity context:
var context = VelocityContext();
context.Put("helper", new Helper());
context.Put("billableStatus", "something");
...
and then in your template:
$helper.Evaluate($billableStatus)
You have to make your helper non-static for this to work, of course.
I came across something similar in past and I was looking for something more sophisticated and with more control. I found that NVelocity does provide a way to intercept the method and property calls but for that you will have to implement certain things. In order to make your custom interceptor you will need to implement NVelocity.IDuck. For example
public class MyClass : NVelocity.IDuck
{
public object GetInvoke(string propName)
{
....
}
public object Invoke(string method, params object[] args)
{
....
}
public void SetInvoke(string propName, object value)
{
....
}
}
Now any instance of MyClass will intercept and pass the method and property calls to our these three function implementation and give us a chance to resolve and return the output. You may notice from these three function signatures that in order to implement them we may need some reflection where we can locate respective methods on available extension types and execute them. If needed you can read following blog post for more details about going this way. NVelocity and extension methods

Resources