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
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.