开发者

Constructor not called consistently

I have a controller which inherits from an abstract secure controller which holds a user object as below.

public new User User
{
  get
  {
    if (this.user == null)
    {
      var id = int.Parse(base.User.Identity.Name, CultureInfo.InvariantCulture);
      this.user = this.UserRepository.FindById(id);
    }

    return this.user;
  }
}

Every time I make a call to the following function I receive a null exception for the above this.UserRepository

[UrlRoute(Path = "api/stats/events/visits/accounttype/{idList}")]
[UrlRoute(Path = "api/{idList}/stats/events/visits/accounttype")]
[UrlRouteParameterDefault(Name = "idList", Valu开发者_如何学运维e = "")]
public virtual ActionResult Vsat(string idList, DateTime? startDate, DateTime? endDate)
{
  // get the ids from the url and retrieve a list of events for those user/s
  var ids = (from id in idList.Split(',') where !string.IsNullOrEmpty(id) select Convert.ToInt64(id)).ToList();
  var allEvents = this.eventRepository.FindForCompanyBetweenDatesForUsers(
      this.User.Company.Id, new List<EventType> { EventType.Visit }, startDate, endDate, ids).ToList();

  var groupResults = allEvents.GroupBy(x => x.Account.AccountType.Name);

  return null;
}

Even though my Api constructor calls the base constructor of Secure Controller like so

public ApiController(IUserRepository userRepository) : base(userRepository)
{
}

protected SecureController(IUserRepository userRepository)
{
  this.UserRepository = userRepository;
}

What's even more strange is that there are other functions on the page which reference this.User and none of them return null the same exception. They hit the secure constructor, then the api constructor and then the function. The above Vsat function (naming just for testing purposes) hits the functions, then breaks on the line

this.user = this.UserRepository.FindById(id);

As well as that, If I place a similar function above that, it works, but the new function then has the same problem.

Edit

Created a new class and the function works perfectly.

public class TestController : SecureController
  {
    private readonly IEventRepository eventRepository;

    public TestController(IUserRepository userRepository, IEventRepository eventRepository) : base(userRepository)
    {
      this.eventRepository = eventRepository;
    }

    [UrlRoute(Path = "test/stats/events/visits/accounttype/{idList}")]
    [UrlRoute(Path = "test/{idList}/stats/events/visits/accounttype")]
    [UrlRouteParameterDefault(Name = "idList", Value = "")]
    public virtual ActionResult Vsat(string idList, DateTime? startDate, DateTime? endDate)
    {
      // get the ids from the url and retrieve a list of events for those user/s
      var ids = (from id in idList.Split(',') where !string.IsNullOrEmpty(id) select Convert.ToInt64(id)).ToList();
      var allEvents = this.eventRepository.FindForCompanyBetweenDatesForUsers(
        this.User.Company.Id, new List<EventType> {EventType.Visit}, startDate, endDate, ids).ToList();

      var groupResults = allEvents.GroupBy(x => x.Account.AccountType.Name);

      return null;
    }
  }


I'm not sure there is enough code to understand exactly where the problem is coming in, but I noticed that your User property uses the new keyword to hide the property below it. This will only work if the calling code uses a reference to ApiController (I assume this is the type with the new User property?).

If you have code that uses SecureController and tries to access User it will not touch the null checking code you have implemented around this.user.

As for inconsistent constructor calls, I can say that if you are new-ing an object, all relevant constructors on the inheritance path will be called, unless an exception is thrown.

See here for an overview about Member Hiding using the new keyword, and associated pitfalls:

  • http://msdn.microsoft.com/en-us/library/Aa691135

Update: I suspect Ninject is playing silly-buggers with your object life span. Either that or construction is doing something funky like this:

How does WCF deserialization instantiate objects without calling a constructor?

I'd say breakpoint your base class constructor and make sure the object provided is not null. Without seeing any more code it's hard to answer. Try creating another question, but focus more on Ninject being a possible source of the problem.


Sorry for the confusion, it turns out the problem was cause by t4mvc templates.

After changing the ApiController the code generation templates needed to be re-ran to reflect the changes.

The constructors are now fired as expected.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜