How to retrieve an object property inside a view - c#

I have an index method in a controller which looks like this :
public ActionResult Index()
{
var object = _ObjectService.GetAll();
return View(object);
}
Which give me a list of object with those properties :
public class Object : EntityWithNameAndId
{
public virtual Site Site { get; set; }
public virtual List<User> Users { get; set; }
public virtual List<Planning> Plannings { get; set; }
public virtual Guid IdPilote { get; set; }
}
Now in my Index() view, i want to get the User who's related to the IdPilote id and display its name.
I tried something like this, thanks to this topic ASP.Net MVC: Calling a method from a view :
#model List<MyClass.Models.Promotion>
#foreach (var item in Model)
{
<td>#item.Site.Name</td>
#{
var id = item.IdPilote;
//Here Interface and Service are folders
var user = MyDAL.Interface.Service.IUserService.Get(id);
}
<td>
//This is where i try to display my User name,
//that i get dynamically using the idPilote for each User in list
</td>
}
But Get(id) is not recognize as a valid method..
public interface IUserService : IDisposable
{
User Get(Guid id);
}
public class UserService : IUserService
{
private MyContext context;
public UserService(MyContext context)
{
this.context = context;
}
public User Get(Guid id)
{
return context.User.Where(w => w.Id == id).SingleOrDefault();
}
}
So what's the best way to get my User object inside my view, since i only get an Id ?
Should i create a new list, using the first one, in my Index method (where i can call IUserInterface.Get()) or is there a better way to do it ?

Make it worked by creating a new list and a specific ViewModel, as suggested :
public class IndexObjectViewModel : EntityWithNameAndId
{
public virtual Site Site { get; set; }
public virtual List<User> Users { get; set; }
public virtual List<Planning> Plannings { get; set; }
//To store User instead of its Id
public virtual User Pilote { get; set; }
}
Now Index() looks like this :
public ActionResult Index()
{
var objects = _IObjectService.GetAll();
ViewBag.NotPromoExist = false;
var indexObj = new List<IndexObjectViewModel>();
foreach (var p in objects)
{
var indexModel = new IndexObjectViewModel();
indexModel.Id = p.Id;
indexModel.Name = p.Name;
indexModel.Site = p.Site;
indexModel.Users = p.Users;
indexModel.Plannings = p.Plannings;
indexModel.Pilote = _IUserService.Get(p.IdPilote);
indexObj.Add(indexModel);
}
return View(indexObj);
}
Everything is done in the controller now. Not sure if it's the best way to do it though..

Related

Mapping problem, object reference not set to an instance

I got a small problem here. I got a course class and a User. I want to show all the Users inside a Course through the API.
the error i get,
'Object reference not set to an instance of an object.'
And this is my controller method,
var objList = _courseRepo.GetUsers(CourseId);
if (objList == null)
{
return NotFound();
}
var objToShow = new List<ViewCourseDetailsDTO>();
foreach (var obj in objList)
{
objToShow.Add(_mapper.Map<ViewCourseDetailsDTO>(obj));
}
return Ok(objToShow);
The Error i got is inside the Foreach-loop. It says that i need to create an object...
This is how my DTO classes looks like,
public class ViewCourseDetailsDTO
{
public int CourseId { get; set; }
public string CourseTitle { get; set; };
public ICollection<UserDTO>? Users { get; set; } = new List<UserDTO>();
}
And this one,
public class UserDTO
{
public string ID { get; set; }
public string UserName { get; set; }
public string Name { get; set; }
}
Do you think i have to break out the UserDTO somehow? Is it Therefore u think ?
if you want to see my CourseRepository than its here,
public ICollection<Course> GetUsers(int courseId)
{
return _db.Course.Where(c => c.CourseId == courseId).Include(a => a.Users).ToList();
}
Would be really grateful if you could help me out here.
Wohooo I found it, damnit!
On my controller, i forgot to put in mapper here,
public CourseController(ICourseRepository courseRepo, IMapper mapper)
{
_courseRepo = courseRepo;
_mapper = mapper;
}
I had injected it correct at the top but forgot to put it inside there ^

Creating dropdownlist from database with Entity Framework Core in an ASP.NET Core 5 MVC application

In my app I'm trying to populate a drop-down menu by taking data from the db with EF Core, but unfortunately I've been trying it for two days without success.
I have tried to do this as recommended in this post, but I keep getting errors.
More specifically the error I'm facing now is
'IEnumerable' does not contain a definition for 'Years' and no accessible extension method 'Years' accepting a first argument of type 'IEnumerable' could be found
This error comes from the view:
#Html.DropDownList(m => m.Years, Model.Years, "-- Select year --")
Here is my model class:
public partial class Bdgfixmonth
{
public int Counter { get; set; }
public int Byear { get; set; }
//
public IEnumerable<SelectListItem> Years { get; set; }
public string Bbudget { get; set; }
public int Bmonth { get; set; }
public string Blongmonth { get; set; }
public int Closed { get; set; }
public string Current { get; set; }
}
And here is my controller for the GET action method Index:
private readonly salesContext _context;
public IEnumerable<SelectListItem> Years { get; set; }
public bdgfixmonthController(salesContext context)
{
_context = context;
}
public async Task<IActionResult> Index()
{
var bdgfixmonths = await _context.Bdgfixmonths.ToListAsync();
IEnumerable<SelectListItem> GetAllYears()
{
IEnumerable<SelectListItem> list = _context.Bdgfixmonths
.AsEnumerable()
.Select(s => new SelectListItem
{
Selected = false,
Text = s.Byear.ToString(),
Value = s.Byear.ToString()
});
return list;
}
Years = GetAllYears();
return View(bdgfixmonths);
}
The goal here is to populate the drop-down menu with the data of the db, and then make a query based on the selected value, so that only the relevant values are shown (in this case based on the year).
Any help would be very appreciated, thanks.
Since you're returning a model that contains a list of Bdgfixmonths, it's probably better to create a view model that looks like this:
public class BdgfixmonthsViewModel
{
public List<Bdgfixmonth> Bdgfixmonths { get; set; }
public IEnumerable<SelectListItem> Years { get; set; }
}
Then, your Action Method will change to:
private readonly salesContext _context;
public bdgfixmonthController(salesContext context)
{
_context = context;
}
public async Task<IActionResult> Index()
{
var vm = new BdgfixmonthsViewModel();
var bdgfixmonths = await _context.Bdgfixmonths.ToListAsync();
IEnumerable<SelectListItem> GetAllYears()
{
IEnumerable<SelectListItem> list = _context.Bdgfixmonths
.AsEnumerable()
.Select(s => new SelectListItem
{
Selected = false,
Text = s.Byear.ToString(),
Value = s.Byear.ToString()
});
return list;
}
vm.Years = GetAllYears();
vm.Bdgfixmonths = bdgfixmonths;
return View(vm);
}
Your ViewModel will have the two collections which can then be used in the view. You will need to update the View to reference the Bdgfixmonth properties like Bdgfixmonths.Bbudget for example. Also, the model will change to something like:
#model IEnumerable<Bdgfixmonth>
becomes
#model BdgfixmonthsViewModel
And then any iteration code will change to:
#foreach (var item in Model.Bdgfixmonths)
{
item.Bbudget
}

How to get specific field(s) from database?

public class UserController : ApiController
{
UserSampleEntities entities = new UserSampleEntities();
// GET api/<controller>
[Route("api/User")]
public IEnumerable<user> Get()
{
{
return entities.users;
}
}
}
This returns the json with all the entries in the database with all its properties. How do I filter such that I can obtain a json for only specific properties?
Create a new class that represents a user using only the properties you want to expose from "api/User":
public class UserDto
{
public int Foo { get; set; }
public string Bar { get; set; }
// add the properties you need here
}
Rewrite your API action to this:
[Route("api/User")]
public IEnumerable<UserDto> Get()
{
return entities.users
.Select(u => new UserDto
{
Foo = u.Foo,
Bar = u.Bar,
// map the properties you need here
})
.ToArray();
}

Exclude controller name from routing in net core asp

I am using asp net core mvc and trying to develop a RESTful app. Let's say I have models like this:
internal class Album
{
public long Id { get; set; }
public string Name { get; set; }
public long ExecutorId { get; set; }
public virtual Executor Executor { get; set; }
}
internal class Executor
{
public long Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Album> Albums { get; set; }
}
And I have 2 controllers, that I wrote like this:
[ApiVersion("1")]
[Route("api/v{api-version:apiVersion}/[controller]")]
public class ExecutorsController : Controller
{
[HttpGet("{id}", Name = "GetExecutor")]
public IActionResult GetById(long id)
{
//some code
}
[HttpGet(Name = "GetExecutors")]
public IActionResult GetAll()
{
//some code
}
}
[ApiVersion("1")]
[Route("api/v{api-version:apiVersion}/[controller]")]
public class AlbumController : Controller
{
[HttpGet("{id}", Name = "GetAlbum")]
public IActionResult GetById(long id)
{
//some code
}
[HttpGet(Name = "GetAlbums")]
public IActionResult GetAll()
{
//some code
}
}
I can call http://localhost:48234/api/v1/Album/1 and get album by Id,
I can call http://localhost:48234/api/v1/Album and get all albums. The same thing works with executors. So, what I want to do, is to be able to get albums by executorId and that my route would look like
http://localhost:48234/api/v1/executors/1/albums, which will return all albums for executor with Id = 1. The problem is that I would like to put this action into AlbumsController:
[HttpGet]
[Route("executors/{executorId}/albums")]
public IActionResult GetAlbumsByExecutorId(long executorId)
{
return new ObjectResult(_service.GetAlbumsByExecutorId(executorId));
}
This code works just fine, but it puts ControllerName (Albums) at the beginning. How can I remove ControllerName from my route? Or maybe I shouldn't do this and just put this action to ExecutorsController? I decided to do it like this, because if action returns albums, it should be placed in AlbumsController. Am I wrong?
Just remove [controller] from route path in controller and move it to the methods.
Something like this:
[ApiVersion("1")]
[Route("api/v{api-version:apiVersion}/")]
public class AlbumController : Controller
{
[HttpGet("album/{id}", Name = "GetAlbum")]
public IActionResult GetById(long id)
{
//some code
}
[HttpGet("album", Name = "GetAlbums")]
public IActionResult GetAll()
{
//some code
}
[HttpGet]
[Route("executors/{executorId}/albums")]
public IActionResult GetAlbumsByExecutorId(long executorId)
{
return new ObjectResult(_service.GetAlbumsByExecutorId(executorId));
}
}
If you want to get albums, you should place action method in AlbumController.
I'd like to recommend you this way:
[HttpGet(Name = 'GetAlbumsByExecutorId')]
[Route("{executorId}/albums")]
public IActionResult GetAlbumsByExecutorId(long executorId)
{
return new ObjectResult(_service.GetAlbumsByExecutorId(executorId));
}

How to map users identity and Auditable properties in view model

This is my view model.
public class ProductViewModel
{
public Guid Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public bool IsAvailable { get; set; }
}
When form is posted from client the form is submitted to this Controller
public async Task<IHttpActionResult> AddProduct(ProductViewModel productViewModel)
{
await ServiceInstances.PostAsync("product/add", productViewModel);
return Ok();
}
Then this controller submit the form to the API controller
Which is on my separate Project.
[HttpPost]
[Route("add")]
public IHttpActionResult AddProduct(ProductViewModel model)
{
_productService.AddProduct(model.UserServiceDetails());
return Ok();
}
Extension UserServiceDetails Where i get the Login User Info
public static UserServiceDetailModel<T> UserServiceDetails<T>(this T model)
{
var serviceRequestModel = new ServiceRequestModel<T>()
{
Model = model,
LoginInfo = HttpContext.Current.User.Identity.GetUserLoginInfo();
};
}
AddProductService:
public void AddProduct(UserServiceDetailModel<ProductViewModel> serviceRequestModel)
{
var repo = _genericUnitOfWork.GetRepository<Product, Guid>();
var mapped = _mapper.Map<ProductViewModel, Product>(serviceRequestModel.Model);
mapped.Id = Guid.NewGuid();
mapped.CreatedDate = GeneralService.CurrentDate();
mapped.CreatedById = serviceRequestModel.LoginInfo.UserId;
repo.Add(mapped);
_genericUnitOfWork.SaveChanges();
}
Now my question is Is there any way to assign the value to this field CreatedDate and CreatedById before posting it to service?
Reduce these logic to mapper:
mapped.CreatedDate = GeneralService.CurrentDate();
mapped.CreatedById = serviceRequestModel.LoginInfo.UserId;
Or is there any way that those field gets mapped to Product when
var mapped = _mapper.Map<ProductViewModel, Product>(serviceRequestModel.Model);
Sometime i may have the List<T> on view-model and there i have to add this field using the loop.
So this same mapping may get repeated over and over on Add Method Or Update.
In some entity i have to assign the ModifiedDate and ModifiedById also.
My Mapper Configuration:
public class ProductMapper : Profile
{
public ProductMapper()
{
CreateMap<ProductViewModel, Product>();
}
}
I cannot add the Enitity as IAuditableEntity and Overrride in ApplicationDbContext because my DbContext is in separate Project and i donot have access to Identity there.

Categories