StructureMap working locally, but not on production server - c#

I developing a MVC5 application, where I am using StructureMap as my DI framework. The application works fine, when I run it locally from Visual Studio. However when I publish to our production server, I get the "No parameterless constructor..." error. I've Googled a solution and found a suggestion to add the code below to an empty constructor in the controller, in order to get a more detailed exception:
public class HomeController : Controller
{
public HomeController()
{
_bll = StructureMap.ObjectFactory.GetInstance<IAgentStatsBll>();
}
private IAgentStatsBll _bll;
public HomeController(IAgentStatsBll bll)
{
_bll = bll;
}
public ActionResult Index()
{
HomeViewModel model = new HomeViewModel {Authors = _bll.GetAuthorsWithCommentsOnDate(DateTime.Now.AddDays(-60))};
return View(model);
}
}
When I run this code on the production server, I get an error saying:
No default Instance is registered and cannot be automatically determined for type 'ZendeskAgentStats.BLL.IAgentStatsBll'.
There is no configuration specified for ZendeskAgentStats.BLL.IAgentStatsBll
If I understand the error correct, it says that SM cannot figure out which concrete type it should use for the IAgentStatsBll interface. However this is configured in the DefaultRegistry.cs:
public class DefaultRegistry : Registry {
#region Constructors and Destructors
public DefaultRegistry()
{
Scan(
scan =>
{
scan.TheCallingAssembly();
scan.AssemblyContainingType<IAgentStatsBll>();
scan.AssemblyContainingType<IAgentStatsDal>();
scan.AssemblyContainingType<IAgentStatsContext>();
scan.AssemblyContainingType<ZendeskAPIMethods>();
scan.WithDefaultConventions();
scan.With(new ControllerConvention());
});
For(typeof(IGenericRepository<>)).Use(typeof(GenericRepository<>));
}
#endregion
}
Can anyone figure out why it is working locally but not on the server?

Related

Azure function suddenly stopped working on Azure with no reason why

I am doing simple telegram echo bot on azure, which write telegramid of user to sql database.
I think i don't need to show code, but i can share with code to you if you require me to do this. I will explain by text.
I have function telegrambot which get response from telegram servers and send it to my UpdateService written by me where messages analyze and if message type is text i will write senders Id to my database.
Firstly i decide to just implement simple echo bot without database.
In startup file i write the next code
[assembly: FunctionsStartup(typeof(MyTelegramBot.Startup))]
namespace MyTelegramBot
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddScoped<UpdateService>();
builder.Services.AddLogging();
}
}
}
And i deploy it to Azure. Everything works fine, every message correctly come back to me.
Next i decide to Add database related files: entities, dbcontext
I have one table user and thats all.
Write operations was hold by IDbSaver
namespace MyTelegramBot.Interfaces
{
public interface IDbSaver<T> where T : class
{
Task<AlertMessage> RegisterUser(T entity);
}
}
Implementation of IDbSaver
namespace MyTelegramBot.Services
{
public class DbSaver<T> : IDbSaver<T> where T : class
{
protected DbSet<T> Dbset;
private readonly MyContext _context;
public DbSaver(MyContext context)
{
Dbset = context.Set<T>();
_context = context;
}
public async Task<AlertMessage> RegisterUser(T entity)
{
await Dbset.AddAsync(entity);
try
{
await _context.SaveChangesAsync();
return new AlertMessage()
{
Message = "Success."
};
}
catch(DbUpdateException ex) when(ex.InnerException is SqlException e)
{
if(e.Number == 2601)
{
return new AlertMessage()
{
Message = "Someone(maybe you?) registered same nickname."
};
}
return new AlertMessage()
{
Message = "some text"
};
}
}
}
}
Registered IDbSaver and Dbsaver in startup like
[assembly: FunctionsStartup(typeof(MyTelegramBot.Startup))]
namespace MyTelegramBot
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddScoped<UpdateService>();
builder.Services.AddLogging();
var connectionString = "connectionstring";
builder.Services.AddDbContext<MyContext>(s => s.UseSqlServer(connectionString));
builder.Services.AddScoped(typeof(IDbSaver<>), typeof(DbSaver<>));
}
}
}
And when i deploy it to Azure, deployment process goes well, no errors during publishing it to azure, but in Azure page of my function Alerting message is
MyTelegramBot: Could not load file or assembly 'Microsoft.Extensions.Logging, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot find the file specified.
In the nuget package menu i found that microsoft.extensions.logging with version 7 and installed it, deploy again but error message still alive.
Guys, can you please help me.
I have next installed packages:
Microsoft.Azure.Functions.Extensions(1.1.0)
Microsoft.EntityFrameworkCore(7.0.0)
Microsoft.EntityFrameworkCOre.SqlServer(7.0.0)
Microsoft.Extensions.Logging(7.0.0)
Microsoft.Net.Sdk.Function(4.1.1)
Telegram.Bot(18.0.0)
Using:
.net 6.0
functions version v4

How to share an InMemory Db between a read and write context

I have am working on a project that needs to support a read db and write db. I have decided to create two contexts accordingly. I have a Web API to interact with the db. I have an endpoint creates a user and another that fetches a user by id. The issue I'm running into is on the Development server, and Local instances, where an InMemory Db is used since development is rather rapid. The issue lies with the read context not giving me the data I stored with the write context. It thinks the table is empty. Upon further examination using the debugger, I am able to navigate and find the "missing" data. I'm not sure what is wrong.
Steps to reproduce
Here is an illustration of what I have in my project
public class WriteContext : IdentityDbContext<User>
{
public WriteContext(DbContextOptions<WriteContext> options) : base(options) {}
}
public class ReadContext : IdentityDbContext<User>
{
public ReadContext(DbContextOptions<ReadContext> options) : base(options) {}
}
public class UserController : Controller
{
private readonly WriteContext _write;
private readonly ReadContext _read;
// constructor injection here
// attributes...
public IActionResult Post(UserModel model)
{
var user = // map model to User
_write.Users.Add(user);
_write.SaveChanges();
return Ok(user);
}
// attributes...
public IActionResult Get(string userId)
{
var user = _read.Users.SingleOrDefault(x => x.Id == userId);
return Ok(user);
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
// other stuff...
services.AddDbContext<WriteContext>(options => options.UseInMemoryDatabase("MemDb"));
services.AddDbContext<ReadContext>(options => options.UseInMemoryDatabase("MemDb"));
// other stuff
}
// other stuff
}
Add a user via write context and then try and fetch user via read context.
Further technical details
EF Core version: 2.0.1
Database Provider: InMemory
Operating system: macOS Sierra
IDE: Jetbrains Rider 2017.2
Corresponding GitHub Issue

Error during InSingletonScope() with Ninject

I have some problem with InSingletonScope().
My interface:
public interface ISettingsManager
{
ApplicationSettings Application { get; }
}
and my class:
public class SettingsManager : ISettingsManager
{
private readonly IConfigurationService _configurationService;
private readonly Lazy<ApplicationSettings> _applicationSettings;
public ApplicationSettings Application { get { return _applicationSettings.Value; } }
private SettingsManager(IConfigurationService context)
{
_configurationService = context;
_applicationSettings = new Lazy<ApplicationSettings>(() => new ApplicationSettings(context));
}
}
and standard binding in NinjectWebCommon looks like this:
kernel.Bind<ISettingsManager>().To<SettingsManager>().InSingletonScope();
kernel.Bind<IConfigurationService >().To<ConfigurationService>().InRequestScope();
And when I use constructor injection or property injection in HomeController:
[Inject]
public ISettingsManager SettingsManager { private get;}
Then I get an error:
An error occurred when trying to create a controller of type 'Web.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor.
Where is the problem? What is wrong with my Singleton?
I use in my project dependency injection and when I inject one interface in constructor, everything work fine. When I add ISettingsManagers I have many problems.
I know what was wrong. The private constructor was the main problem. When I change it to:
public SettingsManager(IConfigurationService context)
then it works like a charm.
The Error it self says its the home controller that needs to be parameterless, however if ninject is setup correctly that is not true, and the bug can be nested down to a single class that does not have the bindings needed.
However, there is one thing that might go wrong in what you show here.
Your configuration is in request scope and your settings is in singleton scope.
This means it might run fine the first time, however in the second attempt, its a new request and the configuration, could be disposed inside your singleton settings, and would proberbly break something.

Using Unity in ASP.NET MVC 4 - Dependency injection error

I'm trying to inject a dependency into a web api controller using Unity.
I followed
http://www.asp.net/mvc/overview/older-versions/hands-on-labs/aspnet-mvc-4-dependency-injection
closely, however I still get error while instantiating constructor, there there's no parameterless constructor.
Controller:
public class ContactsController : ApiController
{
IContactsRepository repository;
public ContactsController(IContactsRepository repository)
{
this.repository = repository;
}
public List<ContactDTO> GetAllContacts()
{
return repository.GetAllContacts().ToList();
}
}
Repository interface and class:
public interface IContactsRepository
{
IEnumerable<ContactDTO> GetAllContacts();
}
Class:
public class ContactsRepository : IContactsRepository
{
public IEnumerable<ContactDTO> GetAllContacts()
{
using (var db = new ContactDatabaseEntities())
{
foreach (var contact in db.Contacts)
{
yield return contact.Convert();
}
}
}
}
I added the line:
Bootstrapper.Initialise();
to Global.asax file, and in Bootstrapper.cs I added:
container.RegisterType<IContactsRepository, ContactsRepository>();
However when i try to access contacts through the url I get the error:
An error occurred when trying to create a controller of type
'ContactsController'. Make sure that the controller has a
parameterless public constructor.
Am I missing something?
I see you are using ApiController - for WebAPI dependency injection is implemented in different way. You are referring to a standard MVC way of resolving dependencies, which won't work for WebAPI.
You need to install Unity.WebAPI package to get it working NuGet

Adding a Service to ServiceStack

I am trying to add a new service to ServiceStack, but it is not being recognized, and my routes are not showing up in the metadata.
This is my service:
public class EventService : Service
{
public object Post(EventRequest event_request)
{
return new EventResponse() {
name = "FirstEvent"
}
}
}
public class EventRequest
{
public int event_id { get; set; }
}
[Route("/event", "POST")]
public class EventResponse {
public string name { get; set; }
}
I have even explicitly referenced the EventService in AppHost, even though they are in the same assembly. I am just adding a service to the basic service tutorial code, and my service is defined within the same namespace as the HelloService.
public AppHost() //Tell ServiceStack the name and where to find your web services
: base("StarterTemplate ASP.NET Host", typeof(HelloService).Assembly, typeof(EventService).Assembly) { }
I have also tried stopping and starting the IIS express service
What am I missing?
It won't work because you have applied your [Route] to the wrong class. You need to have the route defined on the request DTO not the response DTO. So you should define it this way:
[Route("/event", "POST")]
public class EventRequest : IReturn<EventResponse>
{
public int event_id { get; set; }
}
Your action method should define the return type too, rather than type object:
public class EventService : Service
{
public EventResponse Post(EventRequest event_request)
{
return new EventResponse() {
name = "FirstEvent"
}
}
}
You aren't getting metadata defined just now because there are no methods that are using your response EventResponse as a request DTO. So just a really minor thing causing your issue.
Old service assembly in bin:
Remove the SecondWbService.dll from your bin. This is an older service that is being loaded instead of MainWebService.dll - the one that you are actually editing and wanting to run. Because ServiceStack doesn't allow more than one AppHost, WebActivator is finding the older DLL and running it first, thus your service is hidden. After deleting that DLL, rerun the solution and it should be picked up correctly. You can confirm this by adding a breakpoint:
public AppHost() //Tell ServiceStack the name and where to find your web services
: base("StarterTemplate ASP.NET Host", typeof(HelloService).Assembly, typeof(EventService).Assembly)
{ // BREAKPOINT HERE, confirm the assembly is loaded
}
The metadata and service should then work correctly.

Categories

Resources