https://localhost:5001/API/users/ can't be found - c#

when I do API> dotnet run on console, it doesn't show the page of list of users. I'm using sql server express. Here is the github link: https://github.com/joshii22/DatingApp
Error I get.
These are the files I changed.
UserController.cs
[ApiController]
[Route("api/[controller]")]
public class UsersControllers : ControllerBase
{
private readonly DataContext _context;
public UsersControllers(DataContext context)
{
_context = context;
}
[HttpGet]
public ActionResult<IEnumerable<AppUser>> GetUsers()
{
return _context.Users.ToList();
}
[HttpGet("{id}")]
public ActionResult<AppUser> GetUser(int id)
{
return _context.Users.Find(id);
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DataContext>(options =>
{
options.UseSqlServer(_config.GetConnectionString("DefaultConnection"));
});
services.AddControllers();
}
appsettings.Development.json
{"ConnectionStrings" : {
"DefaultConnection" : "server = DESKTOP-QUO7HU2\\SQLEXPRESS; database = datingapp.db; Trusted_Connection = True;" }
DataContext.cs
public class DataContext : DbContext
{
public DataContext(DbContextOptions options) : base(options)
{
}
public DbSet<AppUser> Users { get; set; }
}
When on run this must show.

You should better change the UsersControllers to UsersController.
Or it will not be detected as a controller:
Or,you can change the Route to [Route("api/users")], instead of [controller]
public class UsersController : ControllerBase
{
private readonly DataContext _context;
public UsersController(DataContext context)
{
_context = context;
}
}
The other code are the same as yours and I can get the result:

Related

Global model in controller ASP.NET Core MVC 6

I have Home / Index where show list of Current Tasks, Completed Tasks and form for creating new task.
I created HomeIndexViewModel for pass models (Completed tasks, Current Tasks and TaskCreateViewModel for form) to Index View and there call (#Model.CompletedTasks, #Model.CurrentTasks and #Model.FormCreate)
But in CreatedTaskViewModel I want to get information about validation errors and render them in View. I init in Controller HomeIndexViewModel and get access from Index(Action) and Create(Action).
Approach worked, but I am not sure what it's good idea.
public class HomeIndexViewModel
{
public List<TaskModel> CompletedTasks { get; set; } = new List<TaskModel>();
public List<TaskModel> CurrentTasks { get; set; } = new List<TaskModel>();
public CreateTaskViewModel FormCreate { get; set; } = new CreateTaskViewModel();
}
public class HomeController : Controller
{
private readonly ITaskRepository _taskRepository;
private HomeIndexViewModel homeIndexViewModel;
public HomeController(IConfiguration configuration)
{
_taskRepository = new TaskRepository(configuration.GetConnectionString("AppDB"));
homeIndexViewModel = new HomeIndexViewModel()
{
CompletedTasks = _taskRepository.GetList("completed");
CurrentTasks = _taskRepository.GetList("current");
};
public ActionResult Index()
{
return View(homeIndexViewModel);
}
public ActionResult Create(CreateTaskViewModel task)
{
if (ModelState.IsValid)
{
_taskRepository.Create(task);
}
return View(nameof(Index), homeIndexViewModel);
}
I think you could write a service and inject it to your controller:
public interface ISomeService
{
public HomeIndexViewModel GetHomeIndexViewModel(IConfiguration configuration, ITaskRepository taskRepository)
{
//some codes
HomeIndexViewModel homeIndexView = new HomeIndexViewModel()
{
//some codes
};
return homeIndexView;
}
}
public class SomeService : ISomeService
{
public HomeIndexViewModel GetHomeIndexViewModel(IConfiguration configuration, ITaskRepository taskRepository)
{
//some codes
HomeIndexViewModel homeIndexView = new HomeIndexViewModel()
{
//some codes
};
return homeIndexView;
}
}
In your Startup Class:
public void ConfigureServices(IServiceCollection services)
{
.....
services.AddTransient<ISomeService, SomeService>();
.....
}
In your Controller:
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly ISomeService _someService;
private readonly ITaskRepository _taskRepository;
private readonly IConfiguration _configuration;
public HomeController(ILogger<HomeController> logger, ISomeService someService, ITaskRepository taskRepository, IConfiguration configuration)
{
_logger = logger;
_someService = someService;
_taskRepository = taskRepository;
_configuration = configuration;
}
public IActionResult Index()
{
var homeindexviewmodel = _someService.GetHomeIndexViewModel(_configuration,_taskRepository);
//you could get the homeindexviewmodel in other controllers with the same method
return View();
}
}

Best approach to combine repositories logic

Let's suppose I have 2 repositories:
first is responsible for creating job and return jobId
second is responsible for creating log and take jobId as argument
My goal is to:
save Job and Log simultaneously
prevent situation when in case of error only Job would be saved without Log
What is the most recommended way to get desired result?
I prepared 3 cases which came to my mind but if you see better alternative please share it.
option 1 (getting result and save changes in controller)
public class JobRepository : IJobRepository
{
private readonly Context _context;
public JobRepository(Context context)
{
_context = context;
}
public Guid CreateJob()
{
var job = new Job { Id = Guid.NewGuid() };
_context.Jobs.Add(job);
return job.Id;
}
}
// ...
public class LogRepository : ILogRepository
{
private readonly Context _context;
public LogRepository(Context context)
{
_context = context;
}
public void CreateLog(Guid id)
{
var log = new Log { Jobid = id };
_context.Logs.Add(log);
}
}
// ...
public class JobsController : Controller
{
private readonly Context _context;
private readonly IJobRepository _jobRepository;
private readonly ILogRepository _logRepository;
public JobsController(Context context, JobRepository jobRepository, ILogRepository logRepository)
{
_context = context;
_jobRepository = jobRepository;
_logRepository = logRepository
}
[HttpGet]
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create()
{
var id = _jobRepository.CreateJob();
_logRepository.CreateLog(id);
_context.SaveChanges();
return RedirectToAction("Index");
}
}
option 2 (inject one repository into another)
public class JobRepository : IJobRepository
{
private readonly Context _context;
private readonly ILogRepository _logRepository;
public JobRepository(Context context, ILogRepository logRepository)
{
_context = context;
}
public void CreateJob()
{
var job = new Job { Id = Guid.NewGuid() };
_context.Jobs.Add(job);
_logRepository.CreateLog(job.Id);
_context.SaveChanges();
}
}
// ...
public class LogRepository : ILogRepository
{
private readonly Context _context;
public LogRepository(Context context)
{
_context = context;
}
public void CreateLog(Guid id)
{
var log = new Log { Jobid = id };
_context.Logs.Add(log);
}
}
// ...
public class JobsController : Controller
{
private readonly IJobRepository _jobRepository;
public JobsController(JobRepository jobRepository)
{
_jobRepository = jobRepository;
}
[HttpGet]
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create()
{
_jobRepository.CreateJob();
return RedirectToAction("Index");
}
}
option 3 (do not use context in controller but declare Save method in each repo)
public class JobRepository : IJobRepository
{
private readonly Context _context;
public JobRepository(Context context)
{
_context = context;
}
public Guid CreateJob()
{
var job = new Job { Id = Guid.NewGuid() };
_context.Jobs.Add(job);
return job.Id;
}
public void Save()
{
_context.SaveChanges();
}
}
// ...
public class LogRepository : ILogRepository
{
private readonly Context _context;
public LogRepository(Context context)
{
_context = context;
}
public void CreateLog(Guid id)
{
var log = new Log { Jobid = id };
_context.Logs.Add(log);
}
public void Save()
{
_context.SaveChanges();
}
}
// ...
public class JobsController : Controller
{
private readonly IJobRepository _jobRepository;
private readonly ILogRepository _logRepository;
public JobsController(JobRepository jobRepository, ILogRepository logRepository)
{
_jobRepository = jobRepository;
_logRepository = logRepository
}
[HttpGet]
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create()
{
var id = _jobRepository.CreateJob();
_logRepository.CreateLog(id);
return RedirectToAction("Index");
}
}
As the use case suggests that the operations (saving and logging) should happen as a single unit of work.
I would suggest an approach similar to the third one. But instead of directly injecting both the repositories into the controller. We could create a service that would then make use of the repositories.
Here we can create a service as follows :
public class JobService : IJobService
{
private readonly IJobRepository _jobRepo;
private readonly ILogRepository _logRepo;
public JobRepository(IJobRepository jobRepo, ILogRepository logRepo)
{
_jobRepo = jobRepo;
_logRepo = logRepo;
}
public void CreateJob()
{
var id = _jobRepo.CreateJob();
_logRepo.CreateLog(id);
}
}
public class JobsController : Controller
{
private readonly IJobService _jobService;
public JobsController(IJobService jobService)
{
_jobService = jobService;
}
[HttpGet]
public IActionResult Create()
{
return View();
}
[HttpPost]
public IActionResult Create()
{
_jobService.CreateJob();
return RedirectToAction("Index");
}
}
Additional Reading : The Repository-Service pattern

Using DBContext in repository class

I want to use my DBcontext in my repository class, but I don't know how at the moment. I've tried looking at other questions, but they don't provide the answer needed specific for my case.
I'll start with my controller:
public class MovieController : ControllerBase
{
IMovieService _movieService;
public MovieController(IMovieService movieService)
{
_movieService = movieService;
}
Service class:
public interface IMovieService
{
Movie RetrieveMovie(long id);
IEnumerable<Movie> RetrieveMovies();
}
public class MovieService : IMovieService
{
IMovieRepository _movieRepository;
public MovieService(IMovieRepository movieRepository)
{
_movieRepository = movieRepository;
}
Repository class:
public interface IMovieRepository
{
Movie GetMovieById(long id);
IEnumerable<Movie> GetMovies();
}
public class MovieRepository : IMovieRepository
{
private readonly MusicContext _db;
public Movie GetMovieById(long id)
{
return _db.Movie.Find(id);
}
DBContext:
public class MovieContext : DbContext
{
public MovieContext(DbContextOptions<MovieContext> options)
: base(options)
{
}
public DbSet<Movie> Movies { get; set; }
}
And last my startup function:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MovieContext")));
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Movie.Api", Version = "v1" });
});
}
At the moment Visual studio warns me # MusicContext _db that this field is never assigned to, which I get. How can I get this to work?
you have to add a constructor to a MovieRepository and use DI
public class MovieRepository : IMovieRepository
{
private readonly MovieContext _db;
public MovieRepository (MovieContext db)
{
_db=db;
}
public Movie GetMovieById(long id)
{
return _db.Movie.Find(id);
}
.....
}

How do I use multiple base classes for my CRUD operation in ASP.NET Razor pages

I designed an ASP.NET Core Razor Pages application implementing dropdown list class and using the class as a base for Create, Read and Update classes.
Now I want to implement anonymous authentication and I have created another class for this which should ideally be the base class for the Create, Read and Update classes. When I tried to add it, the system says I cannot use 2 base classes.
How can I use multiple base classes in ASP.NET Core Razor (MVVM)
I tried using both classes but that triggered an error stating I cannot use more than one base class
My dropdown list base class
public class GLRefPageModel: PageModel
{
public SelectList GLRefNameSL { get; set; }
public void PopulateGLRefDropDownList(strMaterialsTransactContext _context, object selectedGLRef = null)
{
var GLRefsQuery = from d in _context.GLRef
select d;
GLRefNameSL = new SelectList(GLRefsQuery.AsNoTracking(), "ID", "Description", selectedGLRef);
}
}
My Authentication base class
public class DI_BasePageModel : PageModel
{
protected ApplicationDbContext Context { get; }
protected IAuthorizationService AuthorizationService { get; }
protected UserManager<IdentityUser> UserManager { get; }
public DI_BasePageModel(
ApplicationDbContext context,
IAuthorizationService authorizationService,
UserManager<IdentityUser> userManager) : base()
{
Context = context;
UserManager = userManager;
AuthorizationService = authorizationService;
}
}
My Edit Class
public class EditModel : GLRefPageModel
{
private readonly strMaterialsTransact.Models.strMaterialsTransactContext _context;
public EditModel(strMaterialsTransact.Models.strMaterialsTransactContext context)
{
_context = context;
}
[BindProperty]
public strMovement strMovement { get; set; }
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
if (strMovement == null)
{
return NotFound();
}
//select the current GLRef
PopulateGLRefDropDownList(_context, strMovement.GLRefID);
return Page();
}
public async Task<IActionResult> OnPostAsync(int? id)
{
if (!ModelState.IsValid)
{
return Page();
}
var strMovementToUpdate = await _context.strMovement.FindAsync(id);
if (await TryUpdateModelAsync<strMovement>(
strMovementToUpdate,
"strmovement", //prefix for form value
s => s.ID, s => s.TransactionDate, s => s.QtyFromStore, s => s.IDPartNbr,
s => s.QtyToStore, s => s.GLRefID, s => s.ShopOrder, s => s.TransactionReason, s => s.TransactionReason,
s => s.OwnerID, s => s.TimeLastAccessed, s => s.Initials, s => s.LastUser))
{
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
//**Select GLRef if TryUpdateModelAsync fails
PopulateGLRefDropDownList(_context, strMovementToUpdate.GLRefID);
return Page();
}
}
I expect to me able to call the base class for my dropdown list operation in my Create, Update and Read operations and also be able to call (and use) the class for the anonymous authentication exercise
I have been able to solve the problem by using composition design pattern all the classes into the DI_BasePageModel class as follows:
public class DI_BasePageModel : PageModel
{
protected ApplicationDbContext Context { get; }
protected IAuthorizationService AuthorizationService { get; }
protected UserManager<IdentityUser> UserManager { get; }
public DI_BasePageModel(
ApplicationDbContext context,
IAuthorizationService authorizationService,
UserManager<IdentityUser> userManager) : base()
{
Context = context;
UserManager = userManager;
AuthorizationService = authorizationService;
}
public SelectList GLRefNameSL { get; set; }
public void PopulateGLRefDropDownList(ApplicationDbContext _context, object selectedGLRef = null)
{
var GLRefsQuery = from d in _context.GLRef
select d;
GLRefNameSL = new SelectList(GLRefsQuery.AsNoTracking(), "GLRefID", "Description", selectedGLRef);
}
Thanks for pointing it out Chris Pratt

How to pass service config to the Xunit project Test controller?

I have below setup currently.
Startup Class : Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.Configure<AzureStorageConfig>(Configuration.GetSection("AzureStorageConfig"));
services.AddTransient<IAzureService, AzureService>();
}
//other config settings ...
}
Class: AzureStorageConfig
//store the azure account details etc...
public class AzureStorageConfig
{
public string AzureURL { get; set; }
public string StorageConnectionString { get; set; }
public string AccountName { get; set; }
}
Interface class: IAzureService
public interface IAzureService
{
Task<string> UploadFileAsync(AzureStorageConfig _storageConfig, string filename);
Task<string> DeleteFile(AzureStorageConfig _storageConfig, string filename);
}
Azure class : AzureService that use by interface above
public class AzureService : IAzureService, IDisposable
{
// Here implemented above service methods..
public Task<string> UploadFileAsync(AzureStorageConfig _storageConfig, string filename)
{
//...
}
Task<string> DeleteFile(AzureStorageConfig _storageConfig, string filename)
{
//...
}
}
Image controller: ImageController.cs
[Produces("application/json")]
[Route("api/Images")]
public class ImagesController : Controller
{
#region Private properties
private readonly ApiDbContext _context;
private readonly IMapper _mapper;
private AzureStorageConfig _storageConfig;
public readonly IAzureService _azureService;
#endregion
#region Constructor
public ImagesController(ApiDbContext context, IMapper mapper, IOptions<AzureStorageConfig> storageConfig, IAzureService azureService)
{
_context = context;
_mapper = mapper;
_storageConfig = storageConfig.Value;
_azureService = azureService;
}
// other POST and Delete methods written
public async Task<IActionResult> PostImage(Guid Id, [FromForm] ICollection<IFormFile> files)
{
// here used _storageConfig objects to use account key and names...
}
}
Main issue in below class ( TEST Library ) with xunit
Class: ImageControllerTest
[Collection("TestDb")]
public class ImageControllerTest : IClassFixture<InitializeAutoMap>
{
private ImagesController _controller;
private DatabaseFixture _fixture;
private InitializeAutoMap _initialize;
public ImageControllerTest(DatabaseFixture fixture, InitializeAutoMap initialize)
{
this._fixture = fixture;
this._initialize = initialize;
// How to pass service object and StorageConfig to the main
//ImageController from this TestController for testing.
_controller = new ImagesController(_context,
_initialize.InstanceMapper,
/*<here I want to pass storageConfig object>*/,
/*<here I want to pass service object>*/
);
}
// other [Fact] testing done.
// other codes..
}
How to it will possible to get injected to Xunit ImageControllerTest constructor.
storageConfig class object and
IAzureService object
into the ImageController from Xunit ImageControllerTest method.?
Share me if you have idea or solutions.

Categories