ASP.NET Core web application - display database data C# - c#

I'm trying to display data from a SQL Server database. I've been struggling with it for a whole day now and still can't find any working solution or tutorial.
What I want to do - make a simple "database browser". The best thing that worked so far was this tutorial https://www.c-sharpcorner.com/article/entity-framework-database-first-in-asp-net-core2/
But I have only one table to display and I don't know how to write this part of code:
public IActionResult Index()
{
var _emplst = _dbContext.tblEmployees
.Join(_dbContext.tblSkills, e => e.SkillID, s => s.SkillID,
(e, s) => new EmployeeViewModel
{ EmployeeID = e.EmployeeID, EmployeeName = e.EmployeeName,
PhoneNumber = e.PhoneNumber, Skill = s.Title,
YearsExperience = e.YearsExperience }).ToList();
IList<EmployeeViewModel> emplst = _emplst;
return View(emplst);
}
for just one table (without any join). Everything I try ends up with an error that I cannot convert tblEmployees to EmployeeViewModel.
Could someone possibly help me? Or suggest any other solution, that might work? I really just want to drag a data from a table and display it on a web page.
EDIT:
ComponentContext.cs:
public class ComponentsContext:DbContext
{
public ComponentsContext(DbContextOptions<ComponentsContext> options) : base(options)
{
}
public DbSet<tblComponents> tblComponent { get; set; }
}
}

Your _emplst list is of a different type (class) than the type (class) EmployeeViewModel.
So you need to go through you list _emplst and transfer the values needed in EmployeeViewModel.
This can be something like this:
public IActionResult Index()
{
var _emplst = _dbContext.tblEmployees.
Join(_dbContext.tblSkills, e => e.SkillID, s => s.SkillID,
(e, s) => new EmployeeViewModel
{ EmployeeID = e.EmployeeID, EmployeeName = e.EmployeeName,
PhoneNumber = e.PhoneNumber, Skill = s.Title,
YearsExperience = e.YearsExperience }).ToList();
var emplst = _emplst.Select( e=> new EmployeeViewModel {
.. i dont known the properties ..
A = e.A,
B = e.B,
... ..
}).ToList();
return View(emplst);
}
As answer to your comment below on the tlbComponent, try this:
var _cmplist = _dbContext.tblComponent.ToList().Select(e => new ComponentsViewModel { ID = e.ID, Name = e.Name, } ).ToList();
IList<ComponentsViewModel> cmplist = _cmplist;
return View(cmplist);
i have change _dbContext.tblComponent.Select(... to _dbContext.tblComponent.ToList().Select(....

Related

ASP.NET Core web api serialize an object's List type property

After the server returned the object, the List type field went missing.
Each EmployeeViewModel has a list of EmployeeContactViewModel objects. The intended logic is, after querying the employee object from database, populate the view model in a method, including the list, and return to client.
The view model:
public class EmployeeViewModel
{
public List<EmployeeContactViewModel> EmployeeContacts;
public EmployeeViewModel()
{
EmployeeContacts = new List<EmployeeContactViewModel>();
}
public string EmployeeId { get; set; }
public string EmployeeName { get; set; }
// more fields
}
The method to populate view models:
public EmployeeViewModel GetViewModelFromEmpObject()
{
var vm = new EmployeeViewModel();
var contact1 = this.CONTACTs.Where(e => e.ContactId == 1).FirstOrDefault();
if (contact1 != null)
{
var contactVm1 = new EmployeeContactViewModel();
CopyContactFields(contact1, contactVm1); // method to populate view-model
vm.EmployeeContacts.Add(contactVm1);
}
else
vm.EmployeeContacts.Add(new EmployeeContactViewModel());
var contact2 = this.CONTACTs.Where(e => e.ContactId == 2).FirstOrDefault();
if (contact2 != null)
{
var contactVm2 = new EmployeeContactViewModel();
CopyContactFields(contact1, contactVm2); // method to populate view-model
vm.EmployeeContacts.Add(contactVm2);
}
else
vm.EmployeeContacts.Add(new EmployeeContactViewModel());
// more lines below
}
The api controller method is below. By setting a breakpoint at the return line, I could see the EmployeeContactViewModel list was correctly created.
[HttpGet("{empid:string}")]
public async Task<EmployeeViewModel> GetAsync(string empid)
{
Employee emp = await _context.Employees
.Include(c => c.CONTACTs)
.Where(c => c.EmployeeId == empid)
.FirstOrDefaultAsync();
var viewModel = emp.GetViewModelFromEmpObject();
return viewModel;
}
However on the client side, although all the other fields (EmployeeId, EmployeeName, etc.) were present in the response, there was nothing for EmployeeContacts list, when inspecting the server response in the browser network tab.
I tried to search before asking but using "Serialize" as a keyword would just get topics on how to do serialization. Any advice is appreciated.
Do you mean that EmployeeContacts is not included in the response result?
You can install Microsoft.AspNetCore.Mvc.NewtonsoftJson, and add this line in Program.cs:
builder.Services.AddMvc().AddNewtonsoftJson(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});

Filtering from list of C# or LINQ

I am trying to filter from attachList the taxheaderID, it comes from my database which is structured as such.
public int attachmentID { get; set; }
public int headerID { get; set; }
public string uploadedfilename { get; set; }
public string originalfilename { get; set; }
public string foldername { get; set; }
Here is the code that gets data from the database:
public JsonResult GetAllAttach()
{
using (car_monitoringEntities contextObj = new car_monitoringEntities())
{
var attachList = contextObj.car_taxcomputationattachment.ToList();
return Json(attachList, JsonRequestBehavior.AllowGet);
}
}
These are my attempts:
attachList
.Select(x => x.headerID)
.Where(x => x == x)
.Take(1);
and:
attachList = attachList
.Where(al => attachList
.Any(alx => al.taxheaderID == alx.headerID
&& al.headerID == alx.headerID));
The problem is I want to parse multiple attach on a single headerID or filter them base on headerID. For example:
Problem to fix:
This is the table
Desired output:
Combined
data table:
data table
data table 2
Here is the actual solution that was made to get the output, but my coworker told me that it is not a good practice that's why I'm trying to filter it in the function itself. apologies for the trouble, thanks!
<div ng-repeat="att in attach|filter:{headerID:header.headerID}:true">
{{att.uploadedfilename}} <br />
</div>
To get attachments by Id
public JsonResult GetAllAttach(int headerId)
{
using (car_monitoringEntities contextObj = new car_monitoringEntities())
{
var attachList = contextObj.car_taxcomputationattachment
.Where(x => x.headerID == headerId)
.ToList();
return Json(attachList, JsonRequestBehavior.AllowGet);
}
}
If you want to have all data in one JSON result, then you need to create a nested view model.
Assuming you have the header id on which you want to filter in a local variable, you are almost correct
int headerIdToFind = 19;
// think of x as a local variable inside a foreach loop which
// iterates over each item in the attachList (it does not exist
// outside the where method)
// this is what you got wrong when you compared the item to itself
var filteredAttach = attachList.Where(x => x.headerId = headerIdToFind);
// if you want to select only some properties based on header id
// you can use select to project those properties
var filteredAttach = attachList.Where(x => x.headerId = headerIdToFind).
Select(x => new {x.attachmentId, x.folderName});
// based on last image, you only want to select (project) header id and the
// filename. so you do not need where (filter) at all
// you can put all the properties you need in the select clause
var filteredAttach = attachList.Select(x => new {x.headerId, x.attachmentId});
// you can enumerate the filtered attach list of convert it into a list
var filteredAttach = filteredAttach.ToList();

Asp.net 5 WebApi 2.0 partial response

I'm working on LinQ to Entity,
Here is my working code:
var products = from p in AppContext.Products
join ... //joins tables
where ... //conditions
select p;
var result = products.OrderBy(p => p.Name);
//Move it to custom format.
return result.Select(p => new
{
p.Id,
p.Name,
p.Description,
...
/*This looks ugly and need to be moved out to somewhere else*/
Categories = FindCategories(p.Id, true),
MetaData = AppContext.ProductMetas.Where(pm => pm.ProductId == p.Id),
Photos = AppContext.ProductPhotos.Where(pp => pp.ProductId == p.Id)
}).Skip(skip).Take(take);
However, I would like to move 'return new...' part into somewhere else (better inject asp.net api handler when transform object to json). For example:
//GetAll()
...
var products = from ... in ... select p;
return products;
//How to register some handler
var results = new List<object>();
foreach (var product in resultSet) {
//merge objects into result set
results.Add(new {/*Merge properties together*/})
}
But I don't know how to do this. Anyone familiar with this, please help.
I’m not quite clear on whether you need assistance with the actual mapping of the object in Linq to Entities or how to add this logic to an ASP.NET 5 route, I am assuming it is the latter.
One approach would be to create a DTO, that will contain the entity and relation data you require, like so:
public class ProductDTO
{
public int Id {get;set;}
public string Name {get;set;}
public List<Category> Categories {get;set;}
...
}
You will then need to create a controller to handle the request:
[Route("api/[controller]")]
public class ProductController : Controller
{
[HttpGet]
public IActionResult GetAll()
{
var products = //..make call to service or query to get products..
var results = new List<ProductDTO>();
foreach (var product in products)
{
// merge objects into new ProductDTO collection
results.Add(a=> new ProductDTO() {Id = a.Id, Name = a.Name ...});
}
return new JsonResult(values);
}
}

Explicit construction of entity type 'Artist' in query is not allowed

Compile just fine but execution fail with the error in the title.
ArtistService.cs
public class ArtistService : IArtistService
{
public List<Artist> ArtistDetail()
{
using (ArtistDataContext db = new ArtistDataContext())
{
return (from artist in db.Artists
select new Artist()
{
Id = artist.Id,
Artist_name = Artist.Artist_name
}).ToList(); <=== error happened here
}
}
}
code Behind
private List<ArtistServiceReference.Artist> ArtistDetail()
{
ArtistServiceReference.ArtistServiceClient client = new
ArtistServiceReference.ArtistServiceClient();
ArtistServiceReference.Artist[] artists = client.ArtistDetail();
return artists.ToList();
I want to move the Artist List to a DropdownList.
The error is happening in the ArtistService.cs at the end {).ToList();
Any explanation on how to fix this issue? Thanks
I based my code on this example and this example is working fine.
example code MyService.cs
public class MyService : IMyService
{
public List<Task> GetTasks()
{
using (TasksDataContext db = new TasksDataContext())
{
return (from task in db.TasksLists
select new Task()
{
Id = task.taskId,
Name = task.taskName,
}).ToList();
}
}
}
Example default.aspx.cs
private List<TaskService.Task> GetTasks()
{
TaskService.MyServiceClient client = new TaskService.MyServiceClient();
TaskService.Task[] tasks = client.GetTasks();
return tasks.ToList();
}
I don't understand why this example will work and not mine. The only difference was this example is returning to a gridview and I want to return to a dropdownlist.
Linq to Entities cannot translate the Artist object creation into SQL code (really, what is this supposed to look like?). Linq to Entities can only execute SQL queries and map returned fields to some entity to which it knows how to map (i.e. your DbSet entities). So, you need to execute the query first and then create the Artist entities locally:
public class ArtistService : IArtistService
{
public List<Artist> ArtistDetail()
{
using (ArtistDataContext db = new ArtistDataContext())
{
return (from artist in db.Artists
select new { // select only columns you need
artist.Id,
artist.Artist_name
})
.AsEnumerable() // execute query
.Select(x => new Artist { // create instance of class
Id = x.Id,
Artist_name = x.Artist_name
})
.ToList();
}
}
}
BTW it looks like you have Artist entities in your Artists DbSet. Why not simply return
return db.Artists.ToList();

MVC4 - Make a value global to whole project

I am using database with multiple language support. Now the problem is that I need to enter my language into query in order to get information and it is fine, but what would be optimal way to store that information.
On client side it will be stored in cookies, of course. Now only way I can think of is making global variable on class and then use it in my functions. Is that only way?
Example code
private string lang = Infrastructure.UserSettings.Language(); // I don't have this implemented yet
[HttpGet]
public dynamic List()
{
string lang = "English"; // That's why I set it here manually for testing
var items = _db.Items.OrderByDescending(x => x.ID).Select(x => new
{
ID = x.ID,
Price = x.Price,
Name = x.ItemTranslations.Where(y => y.Language.Name == lang).Select(y => y.Name).SingleOrDefault(),
Category = new {
ID = x.Category.ID,
Name = x.Category.CategoryTranslations.Where(y => y.Language.Name == lang).Select(y => y.Name).SingleOrDefault()
}
});
return items;
}
My question: Is this good way of doing this or there is some more optimal way?
You could make a base controller with a read-only variable, like so:
public class BaseController : Controller
{
public string UserLanguage
{
get
{
var cLanguage = HttpContext.Request.Cookies["lang"];
if (cLanguage != null)
return cLanguage.Value;
else
return "English";
}
}
}
Then inherit your base controller, like so:
public class HomeController : BaseController
Then access your variable like so:
var items = _db.Items.OrderByDescending(x => x.ID).Select(x => new
{
ID = x.ID,
Price = x.Price,
Name = x.ItemTranslations.Where(y => y.Language.Name == UserLanguage).Select(y => y.Name).SingleOrDefault(),
Category = new {
ID = x.Category.ID,
Name = x.Category.CategoryTranslations.Where(y => y.Language.Name == lang).Select(y => y.Name).SingleOrDefault()
}
});
You would just need to set the cookie at a particular time.
A cookie is sent to the server on every page request. If the setting is available in the cookie, just read the cookie when you need to do a query. There is no performance overhead for reading a cookie that is already present.

Categories

Resources