Code Bug Fix: How to register IHubContext in a dependency container like SimpleInjector for web api in Asp.Net Core?

Original Source Link

my project is built on Asp.Net Core and is using SimpleInjectorWebApiInitialer for registering dependencies and while injecting those dependencies, it reads it’s corresponding implementation registered.
Example:

var container = new Container()
container.Register<IUserService, UserService>(Lifestyle.Scoped);

In my case, I am injecting IHubContext in my classes to call client methods but while initializing the classes, it throws an exception to register IHubContext. So, how should we register it in this scenario?

Since you are using .NET Core, SignalR is already native for it. So you don’t need to inject it to the service. Using app.UseSignalR on Configure and services.AddSignalR() on ConfigureServices already do what you want. Then you just need to call the dependency in your managers like IHubContext<YourHubHub, IYourHub>.

Tagged : / / /

Code Bug Fix: Shared resource localization is not working

Original Source Link

I am working on shared resource localization in Asp .Net Core 3.1. For that I created resource directory and created SharedResources.cs file.

Root/Resources/SharedResources.cs
Root/Resources/SharedResources.en.resx

I injected code in controller.

public AccountController(IStringLocalizer<SharedResources> sharedLocalizer)
{
_sharedLocalizer = sharedLocalizer;
}
public IActionResult Login(LoginViewModel model)
{
if(loginSuccess == true)
{
  return RedirectToAction("Dashboard", "Dashboard");
}
TempData["Error"] = _sharedLocalizer["Error"];
return View(model);

In SharedResources.en.resx

Key : Error
Value : Invalid User

In SharedResources.cs

namespace RootName
public class SharedResources
{
}

It displays Error and it should display Invalid User. Where am I wrong?

For asp.net core 3.x,you need to create SharedResources.cs in your root folder and create SharedResources.en.resx in root/Resources folder like below:

enter image description here

Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddLocalization(o =>
    {
        // We will put our translations in a folder called Resources
        o.ResourcesPath = "Resources";
    });
    services.Configure<RequestLocalizationOptions>(options =>
    {
        var supportedCultures = new[]
            {
            new CultureInfo("en"),
            new CultureInfo("de"),
        };
        options.DefaultRequestCulture = new RequestCulture("en");
        options.SupportedCultures = supportedCultures;
        options.SupportedUICultures = supportedCultures;
    });       
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }


    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseRouting();

    var localizationOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value;
    app.UseRequestLocalization(localizationOptions);

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });  
 }

Tagged : / / / /

Code Bug Fix: Is the same thread used for each individual HTTP transaction in IIS on Azure?

Original Source Link

I am creating an ASP.NET Core 3.1 WebApp which is hosted on Azure and needs to support users from a variety of different cultures – en-GB, en-US, fr-CH, de-CH, etc.

Is the same thread used for each individual HTTP transaction in IIS on Azure, so I can be sure that the thread to which I set current Culture / UICulture upon receipt of request message from the user’s browser will be the same as the thread used to deliver the response message back to the same user?

CultureInfo Culture = new CultureInfo("en-GB");
Thread.CurrentThread.CurrentCulture = Culture;
Thread.CurrentThread.CurrentUICulture = Culture;

Are there any configuration settings on IIS or Azure that might change the situation?

Tagged : / / / /

Code Bug Fix: Create Web.Api post request and receive response using C# console application

Original Source Link

I need to add a new vehicle to the collection from the console application in Web.API
I need to add a vehicle by console and send a post request to the server post, the problem is that it’s created, but it doesn’t go to the server

VehicleController here is post request

      [HttpPost]

        public IActionResult Post([FromBody]Vehicle vehicle)

       {

               // vehicleService.Create();

          return CreatedAtAction(nameof(Post), vehicle);
         }

Program here i need to add vehicle with web.api

case "7":
                    {
                        Console.Write("Enter vehicle to add (VehicleType Balance): ");
                        var vehicleStr = Console.ReadLine();
                        try
                        {
                            var vehicleArgs = vehicleStr.Split();
                            var id = Vehicle.GenerateRandomRegistrationPlateNumber();
                            var type = (VehicleType)Enum.Parse(typeof(VehicleType), vehicleArgs[0]);
                            var balance = decimal.Parse(vehicleArgs[1]);
                            try
                            {


                                var vehicle = new Vehicle(id, type, balance);

                                var response = await client.PostAsync("vehicles/",
                                    new StringContent(JsonConvert.SerializeObject(vehicle), Encoding.Default, "application/json"));
                            }
                            catch (ArgumentException ex)
                            {
                                Console.WriteLine(ex.Message);
                            }
                        }
                        catch
                        {
                            Console.WriteLine("Invalid Vehicle Format");
                        }
                    }

class parking here I create a collection Vehicle

 public class Parking
   {
    //singleton
    private static Parking instance;
    public List<Vehicle> Vehicles; 
    public Parking(int capacity, decimal balance)
    {
        Capacity = capacity;
        Balance = balance;
    }
    public decimal Balance { get; set; }
    public int Capacity { get; }

   // singleton
    public static Parking Instance
    {
        get
        {
            if (instance == null)
                instance = new Parking(Settings.ParkingCapacity, Settings.ParkingBalance);
            return instance;
        }
    }
}

Class Parking service where i create a parking object

public class ParkingService : IParkingService
   {
    private List<TransactionInfo> transactions = new List<TransactionInfo>();
    private readonly ILogService logService;
    private readonly ITimerService withdrawTimer;
    private readonly ITimerService logTimer;
    private readonly Parking parking;
    public ParkingService(ITimerService withdrawTimer, ITimerService logTimer, ILogService logService)
    {
                  this.logService = logService;
        this.withdrawTimer = withdrawTimer;
        this.logTimer = logTimer;
        //parking = new Parking(Settings.ParkingCapacity, Settings.ParkingBalance);
        parking = Parking.Instance;
        parking.Vehicles = new List<Vehicle>();
        this.withdrawTimer.Elapsed += WithdrawTimer_Elapsed;
        this.logTimer.Elapsed += LogTimer_Elapsed;
        this.withdrawTimer.Interval = Settings.FeeChargeInterval.TotalMilliseconds;
        this.logTimer.Interval = Settings.LogWriteInterval.TotalMilliseconds;
        this.withdrawTimer.Start();
        this.logTimer.Start();
    }
public void AddVehicle(Vehicle vehicle)
    {
        if (GetFreePlaces() == 0)
            throw new OverflowException("You vialated the limit");
        if (parking.Vehicles.Select(v => v.Id).Contains(vehicle.Id))
            throw new ArgumentException("Vehicle with this Id is already exists in the parking");
        parking.Vehicles.Add(vehicle);
    }

}

Tagged : / /

Code Bug Fix: No result in my result view of Quick watch but the result is under non-public members

Original Source Link

in my query when i see quick watch, under the result it returns no result but when go through Non-Public members under source and result in view I see all my results,how can i access to them? and why its like this?im using PostgreSQL for my database

 var test = (from t in db.v_vpn_gateway.AsEnumerable()
                    where t.turbine_id.ToString() == id
                    select new TurbineDvce
                    {
                        Comments = "VPN Gateway",
                        Description = string.Empty,
                        DeviceIP = t.vpn_gateway.ToString(),
                        DeviceType = t.device_type,
                        FirmwareVersion = string.Empty,
                        Model = t.model,
                        Password = string.Empty,
                        Phone = string.Empty,
                        Producer = t.producer,
                        PublicIP = t.vpn_public_ip.ToString(),
                        TurbineId = t.turbine_id.ToString(),
                        Username = string.Empty
                    });

Looks like you need to “Hydrate” the result. The way Linq works with Lazy Evaluation, really you are just getting a place holder back for the test variable, and the actual query will run when the test variable is used by other code. Since you have a “where” clause, you should be expecting back an IEnumerable, so you can add ToList() or ToArray() to the end of your query, which will force the query to run and store the list or array in your test variable. That should give you access to that data right after the query runs.

Tagged : /

Code Bug Fix: How do I test the Asp.Net Core controller which has Db Context and Logger?

Original Source Link

I have a controller with two parameters and need to test them via unit tests. Want to test 4 parameters, ViewBug, etc. But how I can make fake DB context and logger? I’m stuck at this moment:

        [Fact]
    public void IndexReturnsAViewResultWithAListOfUsers()
    {
        // Arrange
        var mock = new Mock<AircraftsController>();
        var controller = new AircraftsController(/*params*/);

        // Act

        // Assert
    }

This is my controller:

 public class AircraftsController : Controller
{
    #region DbContext, Logger
    public AppDbContext Context { get; }
    private readonly ILogger<AircraftsController> _logger;

    public AircraftsController(AppDbContext context, ILogger<AircraftsController> logger)
    {
        Context = context;      
        _logger = logger;
        _logger.LogDebug(1, "NLog injected into Controller");
    }
    #endregion



    [HttpGet]
    public IActionResult Compare(int vehicle1, int vehicle2, int vehicle3, int vehicle4)
    {
        var planesFromDb = Context.Planes.OrderBy(x => x.BR).ToList();
        planesFromDb.Insert(0, new Plane { Image = "~/images/EmptyPlane.png", Nation = "EmptyFlag", Name = "Select aircraft", VehicleId=0 });
        var selectedPlanes = new List<Plane>();
        ViewBag.AllPlanesSelected = planesFromDb;

        selectedPlanes.Add(planesFromDb.FirstOrDefault(p => p.VehicleId == vehicle1));
        selectedPlanes.Add(planesFromDb.FirstOrDefault(p => p.VehicleId == vehicle2));
        selectedPlanes.Add(planesFromDb.FirstOrDefault(p => p.VehicleId == vehicle3));
        selectedPlanes.Add(planesFromDb.FirstOrDefault(p => p.VehicleId == vehicle4));

        _logger.LogInformation("Log Message");

        return View(selectedPlanes);
    }

}

As Stephen has suggested the in-memory provider is a good option for mocking an EFCore db context. It works for most things.

I have a requirement to use Moq for 3rd party dependencies so I’d create mocks for both. For the db context I’d use EntityFrameworkCore.Testing (disclaimer, I am the author):

var mockedDbContext = Create.MockedDbContextFor<AppDbContext>();

Then for the logger I’d create a mock using Mock.Of

var mockedLogger = Mock.Of<ILogger<AircraftsController>>();

Easy one liners that you can then use to create your controller in your unit test. Overall I am an advocate of using the EFCore in-memory provider if it suits the unit test. Using mocks does have other advantages such as allowing you to verify invocations.

In .NET Core, you can take advantage of in-memory databases for unit tests. There are two options, EF In-Memory database, and SQLite In-Memory database. I prefer SQLite In-Memory because it gives you all the advantages of handling relational data, unlike EF In-Memory.

Testing with the EF In-Memory Database

SQLite In-Memory Database

Below is a simple implementation for unit tests using SQLite In-Memory database:

    public YourContext GetDbContext()
    {
        var connection = new SqliteConnection("DataSource=:memory:");
        connection.Open();

        var option = new DbContextOptionsBuilder<YourContext>()
            .UseSqlite(connection,
            s => {
                s.UseNetTopologySuite();
                s.MigrationsHistoryTable("__MigrationHistory");
            }).Options;

        var dbContext = new YourContext(option);

        //Added to recreate database and run migration for each test.
        if (dbContext != null)   
        {
            dbContext.Database.EnsureDeleted();
            dbContext.Database.EnsureCreated();
        }

        return dbContext;
    }

And then in unit test:

var context = GetDbContext();

Alternatively, you can place the GetDbContext method in a fixture, so that you are only re-creating the database one time per test class. Have a dispose method in the fixture to run the dbContext.Database.EnsureDeleted() to clean up the data between test classes.

Shared context between Tests – Class Fixtures

Tagged : / / /

Code Bug Fix: Controller cannot reach Controller in other project because of constructor ASP:NET Core

Original Source Link

I’m new to ASP.NET Core and I’m trying to solve this problem for a week now.
I have a solution with two projects.
And when I start the porject the browser just says:
InvalidOperationException: Unable to resolve service for type ‘TSM_Programm.Data.TSMContext’ while attempting to activate ‘TSM_Programm.Controllers.ResourcesController’.

The first part of the solution is my API-Layer that passes data to a user (currently via postman).
The second project is my Data Access Layer.
This Layer contains several Controllers, all of them using the same constructor, which is the following:

public TSMContext _context;

        public ResourcesController(TSMContext context)
        {
            _context = context;
        }

The TSMContext Class is the following:

namespace TSM_Programm.Data
{
    public class TSMContext : DbContext
    {

        public TSMContext(DbContextOptions<TSMContext> options)
            : base(options)
        {
        }


        public DbSet<Resource> Resources { get; set; }     
        public DbSet<Parameter> Parameters { get; set; }
        public DbSet<ResourceToParameter> ResourceToParameters { get; set; }

        public DbSet<Reservation> Reservations { get; set; }
    }

So far so god, but when I am trying to start the program the controllerof the API-Layer does not seem to be able to handle the constructor.

This is my API-Conrtoller:

namespace TSM_API.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class APIController : ControllerBase  //Base Class without View Support
    {


        //Troublemaker
        public ResourcesController _resources;
        public ParametersController _parameters;
        public ReservationsController _reservations;


        public APIController(ResourcesController resources, ParametersController parameters, ReservationsController reservations)
        {
            _resources = resources;
            _parameters = parameters;
            _reservations = reservations;
        }
        //Function to check if controller works
        //GET: api/API
        [HttpGet]
        public IEnumerable<string> Get()
        {
           // ResourcesController controller = new ResourcesController();
            return new string[] { "value1", "value2" };
        }

The API-Controller was not able to use its own constructors, that’s why I changed the Startup.cs.

namespace TSM_API
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            services.AddMvc().AddApplicationPart(typeof(ResourcesController).Assembly).AddControllersAsServices();
            services.AddMvc().AddApplicationPart(typeof(ParametersController).Assembly).AddControllersAsServices();
            services.AddMvc().AddApplicationPart(typeof(ReservationsController).Assembly).AddControllersAsServices();
            services.AddMvc().AddApplicationPart(typeof(TSMContext).Assembly).AddControllersAsServices();


        }

I’m simply out of ideas on how to solve the problem, since I can’t add the TSMContext class a service.
Any idea how to solve it?

Thank you.

I see you have not registered your dbcontext as a dependency injection. Your issue might be due to ResourceController trying to access _context as a DI but it is not registered. To use the context as a dependency injection, register it in the startup.cs as following.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TSMContext>(options => options.UseSqlServer(Configuration.GetConnectionString("YOUR_CONNECTION_STRING")));

//If you have any services that should be used as DI, then they also must be registered as like this
    services.AddScoped<Interface, Class>(); //Interface refer to the service interface while class is the actual service you will use.
}

Tagged : / / / /

Code Bug Fix: .Net core and Npgsql error on query A command is already in progress

Original Source Link

Im using Postgres and i get an error while want to run the following query:

     var devices = (from m in db.turbineDevices.AsEnumerable()
                       join c in db.accessinfMaster.AsEnumerable() on
                       m.turbine_ip equals c.turbine_id into tmp
                       from tm in tmp.DefaultIfEmpty()
                       join t in db.v_vpn_gateway.AsEnumerable()
                       on m.turbine_ip equals t.turbine_id into tmp2
                       from tm2 in tmp2.DefaultIfEmpty()
                       where m.turbine_ip.ToString() == id

                       select new TurbineDvce
                       {

                           DeviceIP = m.device_ip.ToString(),
                           DeviceType = m.device_type,
                           FirmwareVersion = m.firmware_version,                           
                       }).AsEnumerable().Union(from t in db.v_vpn_gateway
                                               where t.turbine_id.ToString() == id
                                               select new TurbineDvce
                                               {
                                                   Comments = "VPN Gateway",
                                                   Description = string.Empty,
                                                   DeviceIP = t.vpn_gateway.ToString(),
                                                   DeviceType = t.device_type,
                                                   FirmwareVersion = string.Empty,
                                                   Model = t.model,
                                                   Password = string.Empty,
                                                   Phone = string.Empty,
                                                   Producer = t.producer,
                                                   PublicIP = t.vpn_public_ip.ToString(),
                                                   TurbineId = t.turbine_id.ToString(),
                                                   Username = string.Empty
                                               } ).OrderBy(m => m.DeviceIP).ThenByDescending(m => m.Description);

and here is my DbContext:

    services.AddDbContext<DbContextClass>(options =>
        options.UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));

in my controller i inject my context:

    public class AcessInfoData:IAccessInfo
  {
    private DbContextClass db;
    public AcessInfoData(DbContextClass context)
    {
        db = context;
    }

when it reachs my LINQ it gives me an error :Npgsql.NpgsqlOperationInProgressException: A command is already in progress:

 SELECT v.turbine_ip, v.comments, v.description, v.device_ip, v.device_type, v.firmware_version, v.model, v.producer, v.psw, v.public_ip, v.tel_number, v.username

Your multiple AsEnumerable calls inside your query are triggering separate commands to be executed, and since they attempt to run concurrently on the same connection, you get an exception (this is not possible).

Any reason for these AsEnumerables? It seems like your query should be translatable to SQL for executing on the server – can you try removing them?

Tagged : / /

Code Bug Fix: In _Header partial, how to query from db to render menu?

Original Source Link

Layout:

<partial name="_HeaderPartial" />
<div class="container">
    <main role="main" class="pb-3">
        @RenderBody()
    </main>
</div>
<partial name="_FooterPartial" />

_Header:

<header>
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
    <div class="container">
        <a class="navbar-brand" asp-controller="Home" asp-action="Index">Admin</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
            <ul class="navbar-nav flex-grow-1">
                <li class="nav-item">
                    <a class="nav-link text-dark" asp-controller="Home" asp-action="Index">Home</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

Now I need to replace nav-item, each page route and name comes from databse. Since there is not a particular corresponded controller for header partial.

So do I have to add ViewBag in each controller? like this:

    public IActionResult Index() // page1
    {
        ViewBag.menus = _svc.getMenu(); 
        return View();
    }

    public IActionResult Thanks() // page2
    {
        ViewBag.menus = _svc.getMenu(); 
        return View();
    }

_Header

                @foreach (var menmu in ViewBag.menus)
                {
                    <li class="nav-item">
                        <a class="nav-link text-dark" asp-controller="@menmu.controller" asp-action="@menmu.action">@menmu.title</a>
                    </li>
                }

I mean I konw its not right to do so, but I don’t know what is the best way to figure it out.

I have done this as follows (in an MVC5 app, it looks like you are using Razor Pages so for you it may be different, but I think it can still help you)

  1. Create a menu partial view, with it’s own Menu model class. Place the markup for your menu there
  2. Add a Menu() method to your HomeController (or some other controller, doesn’t really matter), that returns a PartialViewResult. I’ve marked it as [ChildActionOnly] to make sure it can only be used as partial view. I also added [OutPutCache(Duration = 60)] This method will get the data, create the model and return a call to PartialView("_Menu, menuModel) (or whatever you named the partial view and model)
  3. In your header, add @Html.Action("Menu", "Home") to render the menu
Tagged : / / / /

Code Bug Fix: No certificate found if run as docker image, while certificate returns when running as IISExpress

Original Source Link

I have a asp.net core 3.1 web app where I am trying to get certificate which is available in current user personal store.

When I am running application with IISExpress, I am able to get the certificate,

 X509Store storex = null;
        try
        {
            storex = new X509Store(StoreName.My, StoreLocation.CurrentUser);
            storex.Open(OpenFlags.ReadOnly);
            var certificates = storex.Certificates.Find(X509FindType.FindByThumbprint,
                "23f642c528f747241bb5bef8cd8ff21116dc5bff", true);

           X509Certificate certificatex = certificates[0];
        }

        catch (Exception e)
        {
            throw e;
        }

        finally
        {
            storex.Close();
        }

I have Dockerfile like this for this web application,

#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build
WORKDIR /src
COPY ["DockTest/DockTest.csproj", "DockTest/"]
RUN dotnet restore "DockTest/DockTest.csproj"
COPY . .
WORKDIR "/src/DockTest"
RUN dotnet build "DockTest.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "DockTest.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "DockTest.dll"]	

Now When I am trying to run the application as Docker image, then I am NOT getting the certificate.

How to load certificate to the docker image?

I tried to add certificate like below in dockerfile, but it’s not working

 COPY C:/TEMP/Cert/mycert.pfx

please suggest.

Docker is an isolated environment, so it has no access to host machine resources, including certificate stores.
You may want to copy your certificate to Docker image, and load it with

var x509 = new X509Certificate2(File.ReadAllBytes(fileName));

Note however that it will become available to everyone who has access to the image you build.

Tagged : / /