Using statements in a web api - asp.net-mvc

I found this code here
using (var objCtx = new SchoolDBEntities())
{
var schoolCourse = from cs in objCtx.Courses
where cs.CourseName == "Course1"
select cs;
Course mathCourse = schoolCourse.FirstOrDefault<Course>();
IList<Course> courseList = schoolCourse.ToList<Course>();
string courseName = mathCourse.CourseName;
}
And I am using it in a Get method of a web api. When i use a using statement I get the following error
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection
I I do not use it, then how would I dispose of the context object responsibly?

I use something like this to solve the problem without resorting to eager loading (in fact usually in a generic abstract base controller that I extend, but this example is simplified):
public class MyController : ApiController
{
private SchoolDBEntities _objCtx;
// Singleton ObjectContext
protected SchoolDBEntities objCtx
{
if(_objCtx == null) _objCtx = new SchoolDBEntities();
return _objCtx;
}
// Use singleton objCtx without using wrapper here, in Get() or other methods.
public String Get()
{
var schoolCourse = from cs in objCtx.Courses
where cs.CourseName == "Course1"
select cs;
Course mathCourse = schoolCourse.FirstOrDefault<Course>();
string courseName = mathCourse.CourseName;
return courseName
}
// ApiController implements IDisposable, so you can override Dispose to do clean-up here.
// This is not called until the controller is disposed, so you won't get the error you report.
protected override void Dispose(Boolean disposing)
{
if (_objCtx!= null)
{
_objCtx.Dispose();
_objCtx = null;
}
base.Dispose(disposing);
}
}

Related

MVC - Simple Injector and Attribute calling the Context (EF) Throwing exceptions

If I start my application and let it settle, it works great.
However, when I debug my application and if I close the browser tab before it initializes anything and then call another like localhost:81/Home/Test, it throws an exception on retrieving data from DB (EF).
This exception occurs during a call to a Filter CultureResolver which then calls LanguageService. Inside LanguageService there is a call to the DB to retrieve all the available languages.
I got many different exceptions, like:
The context cannot be used while the model is being created. This
exception may be thrown if the context is used inside the
OnModelCreating method or if the same context instance is accessed by
multiple threads concurrently. Note that instance members of
DbContext and related classes are not guaranteed to be thread safe.
Object reference not set to an instance of an object.
The underlying provider failed on Open.
Those exceptions occur all in the same query, it depends on how much time I left the first tab running.
So it seems it's something like Thread-Unsafe code or this query trying to get items before the Context is initialized.
I've the following:
SimpleInjectorInitializer.cs
public static class SimpleInjectorInitializer
{
/// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary>
public static void Initialize()
{
var container = new Container();
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
InitializeContainer(container);
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters, container);
}
private static void InitializeContainer(Container container)
{
container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();
/* Bindings... */
container.RegisterPerWebRequest<IAjaxMessagesFilter, AjaxMessagesFilter>();
container.RegisterPerWebRequest<ICustomErrorHandlerFilter, CustomErrorHandlerFilter>();
container.RegisterPerWebRequest<ICultureInitializerFilter, CultureInitializerFilter>();
}
}
FilterConfig.cs
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters, Container container)
{
filters.Add(container.GetInstance<ICultureInitializerFilter>());
filters.Add(container.GetInstance<ICustomErrorHandlerFilter>());
filters.Add(container.GetInstance<IAjaxMessagesFilter>());
}
}
CultureResolver.cs
public class CultureResolver : ICultureResolver
{
ILanguageService Service;
public CultureResolver(ILanguageService Service)
{
this.Service = Service;
}
public string Resolve(string CultureCode)
{
// Get the culture by name or code (pt / pt-pt)
ILanguageViewModel language = Service.GetByNameOrCode(CultureCode);
if (language == null)
{
// Get the default language
language = Service.GetDefault();
}
return language.Code;
}
}
LanguageService.cs
public class LanguageService : ILanguageService
{
IMembership membership;
ChatContext context;
ILanguageConverter converter;
public LanguageService(
ChatContext context,
IMembership membership,
ILanguageConverter converter
)
{
this.membership = membership;
this.context = context;
this.converter = converter;
}
public virtual ILanguageViewModel GetByNameOrCode(string Text)
{
string lowerText = Text.ToLower();
string lowerSmallCode = "";
int lowerTextHiphen = lowerText.IndexOf('-');
if (lowerTextHiphen > 0)
lowerSmallCode = lowerText.Substring(0, lowerTextHiphen);
Language item = this.context
.Languages
.FirstOrDefault(x => x.Code.ToLower() == lowerText
|| x.SmallCode.ToLower() == lowerText
|| x.SmallCode == lowerSmallCode);
return converter.Convert(item);
}
public virtual ILanguageViewModel GetDefault()
{
Language item = this.context
.Languages
.FirstOrDefault(x => x.Default);
return converter.Convert(item);
}
}
This is the query that is giving me the exceptions
Language item = this.context
.Languages
.FirstOrDefault(x => x.Code.ToLower() == lowerText
|| x.SmallCode.ToLower() == lowerText
|| x.SmallCode == lowerSmallCode);
Global filters in MVC and Web API are singletons. There is only one instance of such filter during the lifetime of your application. This becomes obvious when you look at the following code:
filters.Add(container.GetInstance<ICultureInitializerFilter>());
Here you resolve the filter once from the container and store it for the lifetime of the container.
You however, have registered this type as Scoped using:
container.RegisterPerWebRequest<ICultureInitializerFilter, CultureInitializerFilter>();
You are effectively saying that there should be one instance per web request, most likely because that class depends on a DbContext, which isn't thread-safe.
To allow your filters to have dependencies, you should either make them humble objects, or wrap them in a humble object that can call them. For instance, you can create the following action filter:
public sealed class GlobalActionFilter<TActionFilter> : IActionFilter
where TActionFilter : class, IActionFilter
{
private readonly Container container;
public GlobalActionFilter(Container container) { this.container = container; }
public void OnActionExecuted(ActionExecutedContext filterContext) {
container.GetInstance<TActionFilter>().OnActionExecuted(filterContext);
}
public void OnActionExecuting(ActionExecutingContext filterContext) {
container.GetInstance<TActionFilter>().OnActionExecuting(filterContext);
}
}
This class allows you to add your global filters as follows:
filters.Add(new GlobalActionFilter<ICultureInitializerFilter>(container));
filters.Add(new GlobalActionFilter<ICustomErrorHandlerFilter>(container));
filters.Add(new GlobalActionFilter<IAjaxMessagesFilter>(container));
The GlovalActionFilter<T> will callback into the container to resolve the supplied type every time it is called. This prevents the dependency from becoming captive which prevents the problems you are having.

Autofac Automocking in ASP.NET MVC

So I'm trying to use Autofac Automocking in ASP.NET MVC 5, but for some reason I can't get it to work.
Here's the test so far:
using (var mock = AutoMock.GetLoose())
{
const string mainUserID = "MainUserID";
const string otherUserID = "OtherUserID";
ApplicationUser user = new ApplicationUser()
{
Id = mainUserID,
UserName = "TestUser"
};
var dataProvider = mock.Mock<IDataProtectionProvider>();
dataProvider.DefaultValue = DefaultValue.Mock;
var userManagerMock = mock.Mock<ApplicationUserManager>();
}
The test fails when mocking the ApplicationUserManager. The error is this:
Result StackTrace:
at Autofac.Extras.Moq.AutoMock.Mock[T](Parameter[] parameters)
at AwenterWeb_NUnit.AccountControllerTest.<Deactivate_User>d__0.MoveNext() in C:\Users\Fabis\Documents\Docs\Kvalifikācijas darbs 2015\AwenterWeb\AwenterWeb-NUnit\AccountControllerTest.cs:line 51
at NUnit.Framework.AsyncInvocationRegion.AsyncTaskInvocationRegion.WaitForPendingOperationsToComplete(Object invocationResult)
at NUnit.Core.NUnitAsyncTestMethod.RunTestMethod()
Result Message: System.InvalidCastException : Unable to cast object of type 'AwenterWeb.ApplicationUserManager' to type 'Moq.IMocked`1[AwenterWeb.ApplicationUserManager]'.
The same thing happens when trying to automock the ApplicationDbContext and it has a very simple constructor, so there shouldn't even be any issues with it.
I'm new to Mocking - what should I do in this scenario?
Edit: Also kind of an unrelated question, maybe you guys know - I've noticed that when creating a Moq for a DbSet using a list created previously in the test, I have to do this:
var dbSetMock = new Mock<IDbSet<DbEntity>>();
dbSetMock.Setup(m => m.Provider).Returns(data.Provider);
dbSetMock.Setup(m => m.Expression).Returns(data.Expression);
dbSetMock.Setup(m => m.ElementType).Returns(data.ElementType);
dbSetMock.Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
It seems really unintuitive. Is there a way to just tell the mock to take the list? So something like:
dbSetMock.Setup(m => m).Returns(data);
Or any other way to create a DbSet Moq from an existing list quickly without having to write those 4 extra lines?
If you look at ligne 73 of MoqRegistrationHandler.cs you can see that only interface is moqable using Autofac.Extras.Moq
var typedService = service as TypedService;
if (typedService == null ||
!typedService.ServiceType.IsInterface ||
typedService.ServiceType.IsGenericType && typedService.ServiceType.GetGenericTypeDefinition() == typeof(IEnumerable<>) ||
typedService.ServiceType.IsArray ||
typeof(IStartable).IsAssignableFrom(typedService.ServiceType))
return Enumerable.Empty<IComponentRegistration>();
var rb = RegistrationBuilder.ForDelegate((c, p) => CreateMock(c, typedService))
.As(service)
.InstancePerLifetimeScope();
You can change the code but it may be quite difficult to make it works with non parameter less dependency.
Can your dependencies be changed to use an interface instead of a concrete class ? if it is not possible and/or if it doesn't make sense, you can use the MockRepository to create your non parameter-less component and then inject it on the AutoMock class.
class Program
{
static void Main(string[] args)
{
using (var mock = AutoMock.GetLoose())
{
/// configure your non interface component with constructor parameters
/// if foo need more complex parameters you can get them
/// using mock.Mock<T>().Object
var fooMock = mock.MockRepository.Create<Foo>((String)null);
fooMock.SetupGet(f => f.Value).Returns("test");
// insert your instance into the container
mock.Provide<Foo>(fooMock.Object);
var bar = mock.Create<Bar>();
Console.WriteLine(bar.GetValue());
}
}
}
public class Foo
{
public Foo(String value)
{
this._value = value;
}
private readonly String _value;
public virtual String Value
{
get
{
return this._value;
}
}
}
public interface IBar
{
String GetValue();
}
public class Bar : IBar
{
public Bar(Foo foo)
{
this._foo = foo;
}
private readonly Foo _foo;
public String GetValue()
{
return this._foo.Value;
}
}
It is not a perfect solution but without big refactoring of the Autofac.Extras.Moq project I can't see any simpler way to do it.

Moq Automapper service in testmethod returns null while mapping

I'm building a website in MVC 4 & using Automapper to map from domain objects to Viewmodel objects. I have injected Automapper as stated here http://rical.blogspot.in/2012/06/mocking-automapper-in-unit-testing.html
and it's working fine inside action methods while debugging, but during unit testing the action method when I inject automapper service I find that service.map is returning null. But while debugging the mapping is fine. I'm not being able to find the reason, trying for over 4 hrs. I have a domain class called Interview & its corrosponding viewmodel as InterviewModel. I have initialized mapping as CreateMap(); in automapper profile config, that has been called from global startup method. Below is the controller & action...
public class NewsAndViewsController : Controller
{
private IInterviewRepository repository;
private IMappingService mappingService;
public NewsAndViewsController(IInterviewRepository productRepository, IMappingService autoMapperMappingService)
{
repository = productRepository;
mappingService = autoMapperMappingService;
}
[HttpPost, ValidateAntiForgeryToken]
[UserId]
public ActionResult Edit(InterviewModel interView, string userId)
{
if (ModelState.IsValid)
{
var interView1 = mappingService.Map<InterviewModel, Interview>(interView);
**// THE ABOVE LINE RETURNING NULL WHILE RUNNING THE BELOW TEST, BUT NOT DURING DEBUGGING**
repository.SaveInterview(interView1);
TempData["message"] = string.Format("{0} has been saved", interView.Interviewee);
return RedirectToAction("Create");
}
return View(interView);
}
}
[TestMethod]
public void AddInterview()
{
// Arrange
var interviewRepository = new Mock<IInterviewRepository>();
var mappingService = new Mock<IMappingService>();
var im = new InterviewModel { Interviewee="sanjay", Interviewer="sanjay", Content="abc" };
mappingService.Setup(m => m.Map<Interview, InterviewModel>(It.IsAny<Interview>())).Returns(im);
var controller = new NewsAndViewsController(interviewRepository.Object, mappingService.Object);
// Act
var result = controller.Edit(im, "2") as ViewResult;
// Assert - check the method result type
Assert.IsNotInstanceOfType(result, typeof(ViewResult));
}
In your test you've got your Interview and InterviewModel classes crossed up in the mappingService.Setup() call (as an aside, I think you could use better naming conventions, or don't use var, to keep your objects clear - "im", "interview" and "interview1" don't make it easy to follow which is the model and which is the view object).
Try this:
[TestMethod]
public void AddInterview()
{
// Arrange
var interviewRepository = new Mock<IInterviewRepository>();
var mappingService = new Mock<IMappingService>();
var interview = new Interview();
var im = new InterviewModel { Interviewee="sanjay", Interviewer="sanjay", Content="abc" };
mappingService.Setup(m => m.Map<InterviewModel, Interview>(im).Returns(interview);
var controller = new NewsAndViewsController(interviewRepository.Object, mappingService.Object);
// Act
var result = controller.Edit(im, "2") as ViewResult;
// Assert - check the method result type
Assert.IsNotInstanceOfType(result, typeof(ViewResult));
}

MongoDB custom serializer implementation

I am new to MongoDB, and am trying to get the C# driver to work serializing F# classes. I have it working with the class automapper using mutable F# fields & a parameterless constructor, but really I need to retain immutability, so I started looking at implementing an IBsonSerializer to perform custom serialization. I haven't found any documentation for writing one of these so have just tried to infer from the driver source code.
I have run into a problem whereby when the Deserialize method is called on the serializer, the CurrentBsonType is set to EndOfDocument rather than the start as I am expecting. I wrote the equivalent in C# just to make sure it wasn't some F# weirdness, but the problem persists. The serialization part seems to work fine and is queryable from the shell. Here is the sample code:
class Calendar {
public string Id { get; private set; }
public DateTime[] Holidays { get; private set; }
public Calendar(string id, DateTime[] holidays) {
Id = id;
Holidays = holidays;
}
}
class CalendarSerializer : BsonBaseSerializer {
public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) {
var calendar = (Calendar) value;
bsonWriter.WriteStartDocument();
bsonWriter.WriteString("_id", calendar.Id);
bsonWriter.WriteName("holidays");
var ser = new ArraySerializer<DateTime>();
ser.Serialize(bsonWriter, typeof(DateTime[]), calendar.Holidays, null);
bsonWriter.WriteEndDocument();
}
public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options) {
if (nominalType != typeof(Calendar) || actualType != typeof(Calendar))
throw new BsonSerializationException();
if (bsonReader.CurrentBsonType != BsonType.Document)
throw new FileFormatException();
bsonReader.ReadStartDocument();
var id = bsonReader.ReadString("_id");
var ser = new ArraySerializer<DateTime>();
var holidays = (DateTime[])ser.Deserialize(bsonReader, typeof(DateTime[]), null);
bsonReader.ReadEndDocument();
return new Calendar(id, holidays);
}
public override bool GetDocumentId(object document, out object id, out Type idNominalType, out IIdGenerator idGenerator) {
var calendar = (Calendar) document;
id = calendar.Id;
idNominalType = typeof (string);
idGenerator = new StringObjectIdGenerator();
return true;
}
public override void SetDocumentId(object document, object id) {
throw new NotImplementedException("SetDocumentId is not implemented");
}
}
This blows up with FileFormatException in Deserialize when the CurrentBsonType is not Document. I am using the latest version 1.4 of the driver source.
I figured this out in the end. I should have used bsonReader.GetCurrentBsonType() instead of bsonReader.CurrentBsonType. This reads the BsonType in from the buffer rather than just looking at the last thing there. I also fixed a subsequent bug derserializing. The updated method looks like this:
public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options) {
if (nominalType != typeof(Calendar) || actualType != typeof(Calendar))
throw new BsonSerializationException();
if (bsonReader.GetCurrentBsonType() != BsonType.Document)
throw new FileFormatException();
bsonReader.ReadStartDocument();
var id = bsonReader.ReadString("_id");
bsonReader.ReadName();
var ser = new ArraySerializer<DateTime>();
var holidays = (DateTime[])ser.Deserialize(bsonReader, typeof(DateTime[]), null);
bsonReader.ReadEndDocument();
return new Calendar(id, holidays);
}

Linq to SQL using Repository Pattern: Object has no supported translation to SQL

I have been scratching my head all morning behind this but still haven't been able to figure out what might be causing this.
I have a composite repository object that references two other repositories. I'm trying to instantiate a Model type in my LINQ query (see first code snippet).
public class SqlCommunityRepository : ICommunityRepository
{
private WebDataContext _ctx;
private IMarketRepository _marketRepository;
private IStateRepository _stateRepository;
public SqlCommunityRepository(WebDataContext ctx, IStateRepository stateRepository, IMarketRepository marketRepository)
{
_ctx = ctx;
_stateRepository = stateRepository;
_marketRepository = marketRepository;
}
public IQueryable<Model.Community> Communities
{
get
{
return (from comm in _ctx.Communities
select new Model.Community
{
CommunityId = comm.CommunityId,
CommunityName = comm.CommunityName,
City = comm.City,
PostalCode = comm.PostalCode,
Market = _marketRepository.GetMarket(comm.MarketId),
State = _stateRepository.GetState(comm.State)
}
);
}
}
}
The repository objects that I'm passing in look like this
public class SqlStateRepository : IStateRepository
{
private WebDataContext _ctx;
public SqlStateRepository(WebDataContext ctx)
{
_ctx = ctx;
}
public IQueryable<Model.State> States
{
get
{
return from state in _ctx.States
select new Model.State()
{
StateId = state.StateId,
StateName = state.StateName
};
}
}
public Model.State GetState(string stateName)
{
var s = (from state in States
where state.StateName.ToLower() == stateName
select state).FirstOrDefault();
return new Model.State()
{
StateId = s.StateId,
StateName = s.StateName
};
}
AND
public class SqlMarketRepository : IMarketRepository
{
private WebDataContext _ctx;
public SqlMarketRepository(WebDataContext ctx)
{
_ctx = ctx;
}
public IQueryable<Model.Market> Markets
{
get
{
return from market in _ctx.Markets
select new Model.Market()
{
MarketId = market.MarketId,
MarketName = market.MarketName,
StateId = market.StateId
};
}
}
public Model.Market GetMarket(int marketId)
{
return (from market in Markets
where market.MarketId == marketId
select market).FirstOrDefault();
}
}
This is how I'm wiring it all up:
WebDataContext ctx = new WebDataContext();
IMarketRepository mr = new SqlMarketRepository(ctx);
IStateRepository sr = new SqlStateRepository(ctx);
ICommunityRepository cr = new SqlCommunityRepository(ctx, sr, mr);
int commCount = cr.Communities.Count();
The last line in the above snippet is where it fails. When I debug through the instantiation (new Model.Community), it never goes into any of the other repository methods. I do not have a relationship between the underlying tables behind these three objects. Would this be the reason that LINQ to SQL is not able to build the expression tree right?
These are non-hydrated queries, not fully-hydrated collections.
The Communities query differs from the other two because it calls methods as objects are hydrated. These method calls are not translatable to SQL.
Normally this isn't a problem. For example: if you say Communities.ToList(), it will work and the methods will be called from the objects as they are hydrated.
If you modify the query such that the objects aren't hydrated, for example: when you say Communities.Count(), linq to sql attempts to send the method calls into the database and throws since it cannot. It does this even though those method calls ultimately would not affect the resulting count.
The simplest fix (if you truly expect fully hydrated collections) is to add ToList to the community query, hydrating it.
Try adding another repository method that looks like this:
public int CommunitiesCount()
{
get { return _ctx.Communities.Count(); }
}
This will allow you to return a count without exposing the entire object tree to the user, which is what I think you're trying to do anyway.
As you may have already guessed, I suspect that what you are calling the anonymous types are at fault (they're not really anonymous types; they are actual objects, which you are apparently partially populating in an effort to hide some of the fields from the end user).

Resources