Foreign key not appearing in View - asp.net-mvc

Can anyone please assist,i have a model that contains a foreign key(ProductCategory).i am trying to call the values of the foreign key but they are not appearing in the view,when i place a breakpoint in the controller all fields appear successful in the raw results view but it seems they are not being passed to the view.
N.B i am using dev express to generate views
public class Product
{
public int Id { get; set; }
public int productCode { get; set; }
public double price { get; set; }
public int ProductCategoryId { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
public Stock itemNo { get; set; }
}
[HttpGet]
public async Task<IActionResult> Get(DataSourceLoadOptions loadOptions) {
var product = _context.Product.Select(i => new {
i.Id,
i.productCode,
i.price,
i.ProductCategoryId,
i.ProductCategory.categoryDescr
});
return Json(await DataSourceLoader.LoadAsync(product, loadOptions));
}
#{
ViewData["Title"] = "Products";
}
<h2 class="content-block">Products</h2>
#(Html.DevExtreme().DataGrid<DevExtremeAspNetCoreApp1.Models.Product>()
.DataSource(ds => ds.Mvc()
.Controller("Products")
.LoadAction("Get")
.InsertAction("Post")
.UpdateAction("Put")
.DeleteAction("Delete")
.Key("Id")
)
.RemoteOperations(true)
.Columns(columns => {
columns.AddFor(m => m.productCode);
columns.AddFor(m => m.price);
columns.AddFor(m => m.ProductCategoryId);
columns.AddFor(m => m.ProductCategory.categoryDescr);
})
.Editing(e => e.Mode(GridEditMode.Popup)
.AllowAdding(true)
.AllowUpdating(true)
.AllowDeleting(true)
.Popup(p=>p
.Title("Product")
.ShowTitle(true)
.Width(500)
.Height(525)
)
)
.Export(e => e.Enabled(true))
)

Try this:
var product = _context.Product.Select(i => new {
i.Id,
i.productCode,
i.price,
i.ProductCategoryId,
ProductCategoryDesc=i.ProductCategory.categoryDescr
});
.....
columns.AddFor(m => m.ProductCategoryDesc);

turns i was passing an anonymous type,correct approach should be:
Controller
public async Task<IActionResult> Get(DataSourceLoadOptions loadOptions) {
var product = _context.Product.Select(i => new {
i.Id,
i.productCode,
i.price,
i.ProductCategoryId,
i.ProductCategory
});
View:
columns.AddFor(m => m.ProductCategory.Id);

Related

Telerik dropdownlist does not seem to bind to JSON

I try to populate the dropdownlist from my database. When loading the view, the dropdownlist spinner appears to do something , then the spinner vanishes and the droplist is empty? Can someone propose a solution. Cheers.
QLine.cs
public partial class QLine
{
[Key]
public int lineId { get; set; }
public int networkId { get; set; }
[Required]
[StringLength(50)]
public string lineName { get; set; }
public virtual QNetwork QNetwork { get; set; }
}
LinesDroplistController.cs
public class LinesDroplistController : Controller
{
private KprModel db = new KprModel();
public JsonResult GetMLines()
{
var result = db.QLines.Where(abc => abc.networkId == 1);
return Json(result, JsonRequestBehavior.AllowGet);
}
}
myView.cshtml
#(Html.Kendo().DropDownList()
.Name("LineDropDownList")
.DataTextField("lineName")
.DataValueField("lineId")
.AutoBind(true)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetMLines", "LinesDroplist");
});
})
)
Please try this:
source.Read(read =>
{
read.Action("GetMLines", "LinesDroplist")
}).ServerFiltering(true);
When the serverFiltering is disabled, then the combobox will not make any additional requests to the server.
It worked when changing
var result = db.QLines.Where(abc => abc.networkId == 1);
to
var result = db.QLines.Where(abc => abc.networkId == 1).Select(x => new { x.lineName, x.lineId });

How to implement mapping via automapper in ASP.NET MVC

I have two class. PRODUCT comes from Entity Framework, and Product in Domain solution: Here are the details:
PRODUCT class (source):
namespace SportsStore.Domain
{
using System;
using System.Collections.Generic;
public partial class PRODUCT
{
public int PRODUCT_ID { get; set; }
public string PRODUCT_NAME { get; set; }
public string PRODUCT_DESCRIPTION { get; set; }
public decimal PRODUCT_PRICE { get; set; }
public string PRODUCT_CATEGORY { get; set; }
}
}
Product class (destination):
namespace SportsStore.Domain.Entities
{
public class Product
{
[HiddenInput(DisplayValue = false)]
public int ProductId {get;set;}
public string ProductName {get;set;}
[DataType(DataType.MultilineText)]
public string ProductDescription {get;set;}
public decimal ProductPrice {get;set;}
public string ProductCategory { get; set; }
}
}
Here is the ProductViewModel that used throughout the project:
public class ProductsListViewModel
{
public IEnumerable<Product> Products { get; set; }
public PagingInfo _pagingInfo { get; set; }
public PagingInfo PagingInfo { get; set; }
public string CurrentCategory { get; set; }
}
Here is my mapping in the project, I have a automapper to map these two.
public static class AutoMapperConfig
{
public static void RegisterMappings()
{
AutoMapper.Mapper.CreateMap<PRODUCT, Product>();
AutoMapper.Mapper.CreateMap<PRODUCT, Product>()
.ForMember(dest => dest.ProductCategory,
opts => opts.MapFrom(src => src.PRODUCT_CATEGORY));
AutoMapper.Mapper.CreateMap<PRODUCT, Product>()
.ForMember(dest => dest.ProductDescription,
opts => opts.MapFrom(src => src.PRODUCT_DESCRIPTION));
AutoMapper.Mapper.CreateMap<PRODUCT, Product>()
.ForMember(dest => dest.ProductId,
opts => opts.MapFrom(src => src.PRODUCT_ID));
AutoMapper.Mapper.CreateMap<PRODUCT, Product>()
.ForMember(dest => dest.ProductName,
opts => opts.MapFrom(src => src.PRODUCT_NAME));
AutoMapper.Mapper.CreateMap<PRODUCT, Product>()
.ForMember(dest => dest.ProductPrice,
opts => opts.MapFrom(src => src.PRODUCT_PRICE));
}
}
I call RegisterMappings in the Global.asax.cs's Application_Start.
protected void Application_Start()
{
AutoMapperConfig.RegisterMappings();
}
Under these circumstances, I read the contents from Entity framework, their type is PRODUCT, when I try to assign it to Product, I got error. The point that I get error is here:
public ActionResult List(string category,int page = 1)
{
List<PRODUCT> pr = null;
using(ProductContext pb = new ProductContext())
{
ProductsListViewModel model = new ProductsListViewModel
{
//Error is here
Products = pb.ProductsList.Where(p => category == null || p.PRODUCT_CATEGORY == category).OrderBy(i => i.PRODUCT_ID).Skip((page - 1) * PageSize).ToList().Take(PageSize).ToList(),
_pagingInfo = new PagingInfo
{
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = category == null ? pb.ProductsList.Count() : pb.ProductsList.Where(e => e.PRODUCT_CATEGORY == category).Count()
},
CurrentCategory = category
};
return View(model);
}
}
The error is this:
Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?)
How can I overcome this? Thanks in advance.
The error says everything you need to know. In somewhere you are trying to put a List of objects to a IEnumerable of the same objects.
It seems to me that you shoud alter the line
Products = pb.ProductsList.Where(p => category == null || p.PRODUCT_CATEGORY == category)
.OrderBy(i => i.PRODUCT_ID)
.Skip((page - 1) * PageSize)
.ToList().Take(PageSize).ToList()
into
Products = pb.ProductsList.Where(p => category == null || p.PRODUCT_CATEGORY == category)
.OrderBy(i => i.PRODUCT_ID)
.Skip((page - 1) * PageSize)
.Take(PageSize).AsEnumerable()

How to join two tables in action result and bind with kendo grid

Hi i am binding kendo grid with two tables below is the sequence i used for that.
public class EFEmployeeRepositary : IEmployeeRepositary
{
private EFDBContext context;
public EFEmployeeRepositary()
{
this.context = new EFDBContext();
}
public IQueryable<Entities.Employee> Employees
{
get
{
return context.Employees;
}
}
public IQueryable<Entities.GetEmployeeDetails> GetEmployeesDetails
{
get
{
return context.GetEmployeesDetails;
}
}
}
[System.ComponentModel.DataAnnotations.Schema.Table("Table1", Schema = "dbo")]
public class Employee
{
[System.ComponentModel.DataAnnotations.Key]
public int Staff_Seq_Number { get; set; }
public string Staff_Number { get; set; }
public string Full_Name { get; set; }
public DateTime DOJ { get; set; }
public DateTime DOB { get; set; }
public string Email_Address { get; set; }
public string Nationality_Code { get; set; }
public int Age { get; set; }
public string Marital_Status_Code { get; set; }
public string Gender_Code { get; set; }
}
[System.ComponentModel.DataAnnotations.Schema.Table("Table2", Schema = "dbo")]
public class GetEmployeeDetails
{
[System.ComponentModel.DataAnnotations.Key]
public int Staff_Seq_Number { get; set; }
public int Matrix_ID { get; set; }
public int Grade_ID { get; set; }
public int Position_ID { get; set; }
}
public class MergeTables
{
public Employee employees { get; set; }
public GetEmployeeDetails GetEmployeesDetails { get; set; }
}
This is my Interface EmployeeRepository class where i added both class
public interface IEmployeeRepositary
{
IQueryable<Employee> Employees { get; }
IQueryable<GetEmployeeDetails> GetEmployeesDetails { get; }
IQueryable<MergeTables> GetMergeTables { get; }
}
This is my dbcontext class
public DbSet<Employee> Employees
{
get;
set;
}
public DbSet<EmployeeHistory> EmployeesHistory
{
get;
set;
}
public DbSet<MergeTables> GetMergeTables
{
get;
set;
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>();
}
This is my controller where called this interface repository
private IEmployeeRepositary employeeRepositary;
public DashboardController(IEmployeeRepositary pEmployeeRepositary)
{
this.employeeRepositary = pEmployeeRepositary;
}
and in same controller i have this actionresult function
public ActionResult Employee_Read([DataSourceRequest] DataSourceRequest request)
{
var p = (from emp in this.employeeRepositary.Employees
join empdetails in this.employeeRepositary.GetEmployeesDetails on emp.Staff_Seq_Number equals empdetails.Staff_Seq_Number
select new MergeTables()
{
});
return Json(p, JsonRequestBehavior.AllowGet);
}
1st Issue: when i am running this i am getting error that "one or more validation errors were detected during model generation has no key defined" which new class MergeTables i created there i am getting issue.
2nd Issue: if i remove mergetables from Repository and and DBContext class this query is working fine but no data is showing in kendo grid
i have shown here two models but more than two models i used and binding in Action result.
Below is the kendo grid code:
#(Html.Kendo().Grid<GEMS.Domain.Entities.MergeTables>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.employees.Staff_Number).Title("EmployeeId");
columns.Bound(p => p.employees.Full_Name).Title("Name");
columns.Bound(p => p.employees.Age).Title("Age");
columns.Bound(p => p.employees.Email_Address).Title("EmailId");
columns.Bound(p => p.GetHierarchyTemp.Department).Title("Department");
columns.Bound(p => p.employees.DOB).Title("Date of birth");
columns.Bound(p => p.employees.DOJ).Title("Date of joining");
columns.Bound(p => p.employees.Marital_Status_Code).Title("Marital Status");
columns.Bound(p => p.employees.Nationality_Code).Title("Nationality Code");
})
.Scrollable()
.Groupable()
.Sortable()
.ColumnMenu()
.Filterable()
.ClientDetailTemplateId("template")
.Resizable(resize => resize.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Multiple)
.Type(GridSelectionType.Cell))
.Navigatable()
.AllowCopy(true)
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(10))
.HtmlAttributes(new { style = "height:380px;" })
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("Employee_Read", "Dashboard"))
)
.Events(events => events.DataBound("dataBound"))
)
can any one help me about these two issues how to fix it
use the word [Key] above your model items.
example:
class telefoon{
[Key]
Int id {get:set}
int number{get:set}
}
like this

Kendo grid image column

working on a MVC4 project, I'm trying to add a column to my kendo grid that displays an image.
<div id="datagrid">
#(Html.Kendo().Grid<SustIMS.Models.ConcessionModel>()
.Name("datagrid_Concessions")
.Columns(columns =>
{
columns.Bound(c => c.Code).Title(ViewBag.lblCode);
columns.Bound(c => c.Description).Title(ViewBag.lblDescription);
columns.Template(#<text>
<img src='#item.Image' />
</text>
).Title("Image");
})
I've tried that but no luck. Also tried:
columns.Template(#<text>
<img src='../../Images/pic.png' />
</text>
).Title("Image");
The images aren't shown, whether I define the image src in the controller or write it directly in the view.
I've checked both this and this question but the images aren't displayed.
Can anyone help?
EDIT
Here's the Concession Model:
public class ConcessionModel
{
public string Id { get; set; }
public string Code { get; set; }
public string Description { get; set; }
public string TrafficOpeningDate { get; set; }
public string CreationDate { get; set; }
public string CreationUser { get; set; }
public string Image { get; set; }
...
The Image property is a string that contains something like "C:\whatever\pic.png"
Try like this,
columns.Template(e => { }).ClientTemplate("<img src='../../Images/pic.png'/>").Width(140).Title("Image");
DEMO:
View
#(Html.Kendo().Grid<Category>().Name("people")
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(m => m.Id);
})
.Read(read => read.Action("GetCategory", "Category"))
)
.Columns(columns =>
{
columns.Bound(c => c.Id);
columns.Bound(c => c.ImageUrl).ClientTemplate("<img src='" + Url.Content("~/CategoryImage/") + "#=ImageUrl#' alt='#=Name #' Title='#=Name #' height='62' width='62'/>");
})
)
Model
public class Category
{
[ScaffoldColumn(false)]
public int Id { get; set; }
public string Name { get; set; }
[UIHint("FileUpload")]
[Required]
public string ImageUrl { get; set; }
public string FileName { get; set; }
internal static object ToDataSourceResult(Kendo.Mvc.UI.DataSourceRequest dsRequest)
{
throw new NotImplementedException();
}
}
Controller
public static List<Category> Category = new List<Category>();
private int _nextid = 4;
static CategoryController()
{
Category.Add(new Category { Id = 1, Name = "Desert", ImageUrl = "Desert.jpg" });
Category.Add(new Category { Id = 2, Name = "Hydrangeas", ImageUrl = "Hydrangeas.jpg" });
Category.Add(new Category { Id = 3, Name = "Tulips", ImageUrl = "Tulips.jpg" });
}
public ActionResult Index()
{
ViewData["Category"] = Category;
return View();
}
public ActionResult GetCategory([DataSourceRequest] DataSourceRequest dsRequest)
{
var result = Category.ToDataSourceResult(dsRequest);
return Json(result);
}

How to use Automapper to create complex viewmodel objects from a simple object and a method call

My application needs to display a table of customer data, including data about the customer and about his most recent order from a given warehouse. The customer domain object contains a GetLatestOrder(warehouseId) method.
I have a CustomerView viewmodel and want to be able to populate it with some fields from the customer object, and a few fields from the latest order object. Can I do this using Automapper?
Try this,
In Global.asax.cs [Application_Start], public static void AppInitialize()
protected void Application_Start(object sender, EventArgs e)
{
Mapper.CreateMap<Order, CustomerViewModel>()
.ForMember(destination => destination.OrderId, options => options.MapFrom(source => source.Id))
.ForMember(destination => destination.OrderName, options => options.MapFrom(source => source.Name));
Mapper.CreateMap<Customer, CustomerViewModel>()
.ForMember(destination => destination.CustmerId, options => options.MapFrom(source => source.Id))
.ForMember(destination => destination.CustmerName, options => options.MapFrom(source => source.Name))
.ForMember(destination => destination.OrderId, options => options.MapFrom(source => Mapper.Map<IEnumerable<Order>, IEnumerable<CustomerViewModel>>(source.Orders).FirstOrDefault().OrderId))
.ForMember(destination => destination.OrderName, options => options.MapFrom(source => Mapper.Map<IEnumerable<Order>, IEnumerable<CustomerViewModel>>(source.Orders).FirstOrDefault().OrderName));
}
And in your code call the mapper like below,
var lstCustomers = new List<Customer>
{
new Customer { Id = 1, Name="Name", Orders = new List<Order> { new Order { Id = 1000, Name ="Some Name"}}},
};
var result = Mapper.Map<IEnumerable<Customer>, IEnumerable<CustomerViewModel>>(lstCustomers);
I am presumed that you classes looks like below,
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public List<Order> Orders { get; set; }
}
public class Order
{
public int Id { get; set; }
public string Name { get; set; }
}
public class CustomerViewModel
{
public int CustmerId { get; set; }
public string CustmerName { get; set; }
public int OrderId { get; set; }
public string OrderName { get; set; }
}
Also refer this post.
Yes, you can:
var vm = new CustomerViewModel();
Mapper.Map(customer, vm);
Mapper.Map(order, vm);
Each mapping will populate the properties it is configured to and leave the rest.
In the end, I took the easy approach, couldn't find another way:
In Application_start:
Mapper.CreateMap<Customer, CustomerView>();
Mapper.CreateMap<Order, CustomerView>();
In the controller method:
IEnumerable<Customer> customers = GetCustomers(false)
.OrderBy(c => c.Name);
IEnumerable<CustomerView> viewData = Mapper.Map<IEnumerable<Customer>, IEnumerable<CustomerView>>(customers);
foreach (Customer customer in customers)
{
CustomerView view = viewData.Where(cv => cv.CustomerId == customer.CustomerId).First();
Mapper.Map(customer.GetLatestOrder(WarehouseId), view);
}

Resources