Data Not getting Updated - Ninject Scope in WebAPI

63 views Asked by At

I am working in web api with ninject as dependency resolver

Scenario:

I need to generate a report as pdf which includes report data and the organisation address as report header.

Current Implementation:

I have 2 controllers namely OrganisationController and ReportController.

  • Organisation Controller have CRUD operation for organisation.
  • Report Controller has get method to get the report details based on id. Here it accepts application/json and application/pdf as Accept header
  • For pdf i created custom PDF Formater and implemented the pdf with MigraDoc tool.

Problem:

While creating pdf, i access organisation data for the header. Pdf generated correctly and it includes organisation data as well. After i updated organisation data using organisation controller put method. When i create report again, it shows the old organisation data.

My suspects:

  • Report1 constructor calls only one time. So organisationLogic not reinitialized. It may due to incorrect dispose or ninject scope.

MyCode:

ninject register code:

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IOrganisationDetailLogic>().To<OrganisationDetailLogic>();
        kernel.Bind<IOrganisationDetailRepository>().To<OrganisationDetailRepository>();

        kernel.Bind<IReport>().To<Report1>();
        kernel.Bind<PdfMediaTypeFormatter>().ToSelf();

    }

Report class:

public class Report1 : IReport
{
    private readonly IOrganisationDetailLogic _organisationLogic;
    public Report1(IOrganisationDetailLogic organisationLogic)
    {
        _organisationLogic = organisationLogic;
    }
    public async Task<MemoryStream> Create(object model)
    {
        MemoryStream stream = null;

        Document document = new Document();

            //Report Header
            SetHeader(section);

          //Report Data here


            //Footer
            SetFooter(section);

            //Render as PDF

        return stream;
    }

    private void SetHeader(Section section)
    {
       //Here we are getting organisation data
        var organisationDetail = _organisationLogic.GetActiveOrganisations().First();

    }
}

Please help where i missed. When i initiated _organisationLogic in the SetHeader itself, its working correct

Update: I am adding my custom formatter class.

public class PdfMediaTypeFormatter : MediaTypeFormatter
    {
        private readonly string mediaType = "application/pdf";
        Func<Type, bool> typeisIPdf = (type) => typeof(IPdf).IsAssignableFrom(type);
        Func<Type, bool> typeisIPdfCollection = (type) => typeof(IEnumerable<IPdf>).
        IsAssignableFrom(type);
        private readonly IReport _report;

        public PdfMediaTypeFormatter(IReport report)
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue(mediaType));
            MediaTypeMappings.Add(new UriPathExtensionMapping("pdf", new MediaTypeHeaderValue(mediaType)));
            this._report = report;
        }

        public async override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
        {
            var memoryStream = await _report.Create(value);

            var bytes = memoryStream.ToArray();
            await writeStream.WriteAsync(bytes, 0, bytes.Length);
        }

//other methods skipped
   }

I read that constructor injection not support in custom formatter please suggest

1

There are 1 answers

4
Mr Slim On

I suspect the scope is what is causing your issue. Try adding .InRequestScope() to relevant registrations to ensure a new instance is a created per request.

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IOrganisationDetailLogic>().To<OrganisationDetailLogic>().InRequestScope();
    kernel.Bind<IOrganisationDetailRepository>().To<OrganisationDetailRepository>().InRequestScope();

    kernel.Bind<IReport>().To<Report1>();
    kernel.Bind<PdfMediaTypeFormatter>().ToSelf();

}