0

I just started having a very strange issue with my custom module that has not started happening until last night. Basically when I try to request the custom view I created for the module the first couple of pages display fine and then all of a sudden the rest of those Content Item pages timeout until I recycle the app pool. (in the browser I get a 324 no data sent error). I also get no errors pertaining to this event in the error logs under the App_Data folder.

Here is the error I receive in the Event Viewer:

3005 
   An unhandled exception has occurred. 
   12/31/2012 12:03:17 PM 
   12/31/2012 5:03:17 PM 
   59d62d1f2da347caafd2dee71266126f 
   43 
   1 
   0 
   /LM/W3SVC/10/ROOT-2-130014459492939950 
   Full 
   / 
   E:\Inetpub\Test-Website\ 
   SERVERNAME 

   24756 
   w3wp.exe 
   NT AUTHORITY\NETWORK SERVICE 
   TimeoutException 
   Transaction Timeout  
   (the url was displayed here)
   admin 
   True 
   Forms 
   NT AUTHORITY\NETWORK SERVICE 
   39 
   NT AUTHORITY\NETWORK SERVICE 
   False 

I do not have this issue on my dev computer (running the website on either iis or visual studio does not recreate the problem).

I am almost positive that the module is set up so that each connection is disposed of efficiently. Also, considering that this has not happened since the site has been up (about a month now) I am guessing it has nothing to do with the code.

Here is an example of how I set up the service classes:

    namespace Example.Services
{
    public interface IDocumentNoteService : ITransientDependency
    {
        List<DocumentNoteRecord> GetNotes(int? packageId, int noteTypeId);
    }

    public class DocumentNoteService : IDocumentNoteService
    {
        private readonly IRepository<DocumentNoteRecord> _docNoteRepo;

        public DocumentNoteService(IRepository<DocumentNoteRecord> docNoteRepo)
        {
            _docNoteRepo = docNoteRepo;
            Logger = NullLogger.Instance;
            T = NullLocalizer.Instance;
        }

        public ILogger Logger { get; set; }
        public Localizer T { get; set; }        

        public List<DocumentNoteRecord> GetNotes(int? packageId, int noteTypeId)
        {
                try {
                    var Notes = _docNoteRepo.Table.Where(x => x.Package_Id == packageId).Where(x => x.Note_Type_Id == noteTypeId).ToList();
                    _docNoteRepo.Flush();
                    return Notes;
                }
                catch (Exception ex) {
                    Logger.Error(ex, "There was a problem getting the document notes for this tour.");
                }
            return Enumerable.Empty<DocumentNoteRecord>().ToList<DocumentNoteRecord>();
        }

    }
}

Here is the code for the part driver:

 namespace ExampleCode.Drivers
{
    public class TourPartDriver : ContentPartDriver<TourPart> {
        private readonly ITourPartService _tourPartService;
        private readonly ITourDateService _tourDateService;
        private readonly IItinDetailService _tourItinDetailsService;
        private readonly IExperiencesService _tourExpService;
        private readonly ITourOptionService _tourOptionService;
        private readonly IDestinationFactService _destinationFactService;
        private readonly IDestinationFactManager _destinationFactManager;
        private readonly IDocumentNoteService _documentNoteService;
        private readonly IPackageUpgradesService _packageUpgradesService;

         public TourPartDriver(
             ITourPartService tourService, 
             ITourDateService tourDateService,
             IItinDetailService tourItinDetailsService,
             IExperiencesService tourExpService,
             ITourOptionService tourOptionService,
             IDestinationFactService destinationFactService,
             IDestinationFactManager destinationFactManager,
             IDocumentNoteService documentNoteService,
             IPackageUpgradesService packageUpgradesService
             ) {
             _tourPartService = tourService;
             _tourDateService = tourDateService;
             _tourItinDetailsService = tourItinDetailsService;
             _tourExpService = tourExpService;
             _tourOptionService = tourOptionService;
             _destinationFactService = destinationFactService;
             _destinationFactManager = destinationFactManager;
             _documentNoteService = documentNoteService;
             _packageUpgradesService = packageUpgradesService;

             Logger = NullLogger.Instance;
             T = NullLocalizer.Instance;
         }

         public ILogger Logger { get; set; }
         public Localizer T { get; set; }

        protected override DriverResult Display(
            TourPart part, string displayType, dynamic shapeHelper) {
            return ContentShape("Parts_Tour", () => shapeHelper.Parts_Tour(
                TourID: part.tour_id,
                TourName: part.tour_name,
                PackageID: part.package_id,
                Highlights: _tourExpService.GetTourExperiences(part.tour_id, part.package_id),
                Description: part.description,
                TourDates: _tourDateService.GetTourDatesDD(part.tour_id),
                TourItinDetails: _tourItinDetailsService.GetItinDetails(part.package_id),
                InitialTourOffsetDate: _tourDateService.GetInitialTourDateOffset(part.package_id),
                TourOptions: _tourOptionService.GetInitialTourOptions(part.package_id),
                TourPrice: _tourDateService.GetTourPrice(part.package_id),
                TourNumDays: _tourItinDetailsService.GetTourNumDays(part.package_id),
                TourNumMeals: _tourDateService.GetTourNumMeals(part.package_id),
                DestinationFacts:_destinationFactManager.GetCategoryFacts(part.package_id),
                PleaseNote: _documentNoteService.GetNotes(part.package_id, (int)NoteTypes.DocNoteType.PleaseNote),
                WebRemarks: _documentNoteService.GetNotes(part.package_id, (int)NoteTypes.DocNoteType.WebRemarks),
                Pace: _documentNoteService.GetNotes(part.package_id, (int)NoteTypes.DocNoteType.Pace),
                PackageUpgrades: _packageUpgradesService.GetInitialPackageUpgrades(part.package_id)
                ));               
        }
    }
}

Here is the code for the view:

@{

List<DocumentNoteRecord> pleaseNote = Model.PleaseNote;
List<DocumentNoteRecord> webRemarks = Model.WebRemarks;
List<DocumentNoteRecord> pace = Model.Pace;

if (pleaseNote.Count > 0)
{
    <h4 class="tourSubTitle1">Please Note</h4>
    foreach (var note in pleaseNote) {
       <p>@Html.Raw(note.Note)</p>
    }
 }

 if (webRemarks.Count > 0) {
         <h4 class="tourSubTitle1">Web Remarks</h4>
         foreach (var noteRemark in webRemarks) {
             <p>@Html.Raw(noteRemark.Note)</p>

         }
     }

if (pace.Count > 0)
{
    <h4 class="tourSubTitle1">Pace</h4>
    foreach (var notePace in pace)
    {
       <p>@Html.Raw(notePace.Note)</p>
    }
 }

}

Any help would be greatly appreciated! I'm definitely in a pickle here.

Thanks.

The Pax Bisonica
  • 2,154
  • 2
  • 26
  • 45
  • How can you be "almost positive that the module is set up so that each connection is disposed of efficiently"? What's IDestinationFactService? When does this code run? – Bertrand Le Roy Dec 31 '12 at 20:30
  • It runs when a specific Content Item is viewed. The only method for this service class is right there. The method is called from the part driver and just displays some information in the view. – The Pax Bisonica Dec 31 '12 at 20:46
  • From what I have read, the transaction should be disposed of when you implement either ITransientDependency, IDependency, or ISingletonDependency.. – The Pax Bisonica Dec 31 '12 at 20:49
  • Please show the code for the driver. The one suspicious thing I see in there is that you're returning a record, and depending on what you do with it, you could be eating up connections. – Bertrand Le Roy Dec 31 '12 at 21:55
  • Alright, I added the code for the driver as well as where it is rendered in the view. One thing to note is I changed the service class because the other one I was showing was actually rendered in the view by a helper, whereas the records returned by this method is passed directly into the view. Thanks for the quick responses! – The Pax Bisonica Dec 31 '12 at 23:32

1 Answers1

0

Never pass a record into a view. Doing so can capture database context and can lead to connection leaks or worse. Build your shape with plain objects that are view-model-like and do not contain persistence entities.

Bertrand Le Roy
  • 17,731
  • 2
  • 27
  • 33
  • I modified all of my existing code so that no records are ever passed into the views. I'll continue to monitor the app to see if I run into any more issues (which could have to do with the server and not Orchard), but it seems this has alleviated the problem for the time being. Thanks for the help. – The Pax Bisonica Jan 04 '13 at 14:34