Hi,
I am using MVC 4, reposistory pattern and EF 4.3, I am trying to display virtual objects that are in my models.
For example in a products model you may have:
public int ProductID {get;set;}
public string Title {get;set;}
public int CategoryID {get;set;}
public double Price {get;set;}
public bool Discontinued {get;set;}
public virtual Category Category {get;set;}
The the category model may be:
public int CategoryID {get;set;}
public string Name {get;set;}
So in my properties CRUD grid I want the user to see the Products.Category.Name rather than the Products.CategoryID.
I also want a dropdown for users to select the Category name from and this would update the products model with the CategoryID.
The problem I get when I reference Products.Category.Name is that the grid displays "UnDefined" in the category column.
Please can someone show me both the controller actions and the view as an example of how this should be achieved.
I am using Razor views.
Many thanks,
Andy
I am using MVC 4, reposistory pattern and EF 4.3, I am trying to display virtual objects that are in my models.
For example in a products model you may have:
public int ProductID {get;set;}
public string Title {get;set;}
public int CategoryID {get;set;}
public double Price {get;set;}
public bool Discontinued {get;set;}
public virtual Category Category {get;set;}
The the category model may be:
public int CategoryID {get;set;}
public string Name {get;set;}
So in my properties CRUD grid I want the user to see the Products.Category.Name rather than the Products.CategoryID.
I also want a dropdown for users to select the Category name from and this would update the products model with the CategoryID.
The problem I get when I reference Products.Category.Name is that the grid displays "UnDefined" in the category column.
Please can someone show me both the controller actions and the view as an example of how this should be achieved.
I am using Razor views.
Many thanks,
Andy
1 Answer, 1 is accepted
0
andrew
Top achievements
Rank 1
answered on 20 Jul 2012, 01:33 PM
I have managed to create custom helpers and populate them, I have also managed to populate the grid with my data, however I cannot save any CREATE, DESTROY or EDIT actions. I believe this is because I need to translate the dynamic proxy fields back to the entity model.
The entity model I am working with is called "Permissions", within permissions there are "User", "Payroll" and "Function" dynamic proxies.
I found that by passing the "Permissions" repository to the grid with Ajax, my UserName, PayrollTitle and FunctionTitle fields were "Undefined".
I played around for a while and eventually managed to change my ajax query as follows to pass in all the required information.
The commented out code is the originally query to pass data to the view.
The problem was that I could not access "Permisions.User.NetLogin", "Permissions.Payroll.Title" and "Permission.Function.Title".
This got the permissions data in to the view and I made some custom editors which can be seen in my view code below:
This covers the Read() actions and custom editors, however I need some help in how I translate both the controller code and possibly the view code (I'm not sure?) so that the UserID, PayrollID and FunctionID are passed back to the "Permissions" Model.
Please can someone help?
Andy
P.S.
Here is my controller:
The entity model I am working with is called "Permissions", within permissions there are "User", "Payroll" and "Function" dynamic proxies.
I found that by passing the "Permissions" repository to the grid with Ajax, my UserName, PayrollTitle and FunctionTitle fields were "Undefined".
I played around for a while and eventually managed to change my ajax query as follows to pass in all the required information.
[HttpPost]
public
ActionResult Read()
{
var perms = unitOfWork.PermissionRepository.Get()
.Select(r =>
new
{ PermissionID = r.PermissionID, UserID = r.UserID, PayrollID = r.PayrollID, FunctionID = r.FunctionID, Level = r.Level, NetLogin = r.User.NetLogin, PayrollTitle = r.Payroll.Title, FunctionTitle = r.Function.Title });
/* var perms = unitOfWork.PermissionRepository.Get()
// Use a view model to avoid serializing internal Entity Framework properties as JSON
.Select(p => new Permission
{
PermissionID = p.PermissionID,
UserID = p.UserID,
PayrollID = p.PayrollID,
FunctionID = p.FunctionID,
Level = p.Level
}).ToList();*/
return
Json(perms);
}
The commented out code is the originally query to pass data to the view.
The problem was that I could not access "Permisions.User.NetLogin", "Permissions.Payroll.Title" and "Permission.Function.Title".
This got the permissions data in to the view and I made some custom editors which can be seen in my view code below:
@section CustomHeader {
@* kendo.common.min.css contains common CSS rules used by all Kendo themes *@
<link href=
"http://cdn.kendostatic.com/2012.2.710/styles/kendo.common.min.css"
rel=
"stylesheet"
/>
@* kendo.silver.min.css contains the
"Blue Opal"
Kendo theme *@
<link href=
"http://cdn.kendostatic.com/2012.2.710/styles/kendo.silver.min.css"
rel=
"stylesheet"
/>
<script src=
"http://cdn.kendostatic.com/2012.2.710/js/kendo.all.min.js"
></script>
}
<h2>Permissions</h2>
<h3>Page Size: <div id=
"comboBox"
></div></h3>
<script>
$(
"#comboBox"
).kendoComboBox({
dataTextField:
"text"
,
dataValueField:
"value"
,
dataSource: [
{ text: 10 },
{ text: 25 },
{ text: 50 },
{ text: 100 },
{ text: 500 }
],
change: function (e) {
var grid = $(
"#grid"
).data(
"kendoGrid"
);
grid.dataSource.pageSize(
this
.value());
}
});
</script>
@* The DIV where the Kendo grid will be initialized *@
<div id=
"grid"
></div>
<script>
$(document).ready(function () {
dataSource =
new
kendo.data.DataSource({
transport: {
create: {
url:
"@Url.Action("
Create
", "
Permission
")"
,
//specify the URL which should create new records. This is the Create method of the HomeController.
type:
"POST"
//use HTTP POST request as the default GET is not allowed for ASMX
},
read: {
url:
"@Url.Action("
Read
", "
Permission
")"
,
//specify the URL which should return the records. This is the Read method of the HomeController.
type:
"POST"
,
//use HTTP POST request as by default GET is not allowed by ASP.NET MVC
},
update: {
url:
"@Url.Action("
Update
", "
Permission
")"
,
//specify the URL which should update the records. This is the Update method of the HomeController.
type:
"POST"
//use HTTP POST request as by default GET is not allowed by ASP.NET MVC
},
destroy: {
url:
"@Url.Action("
Destroy
", "
Permission
")"
,
//specify the URL which should destroy the records. This is the Destroy method of the HomeController.
type:
"POST"
//use HTTP POST request as by default GET is not allowed by ASP.NET MVC
},
parameterMap: function(data, operation) {
if
(operation !=
"read"
) {
// post the products so the ASP.NET DefaultModelBinder will understand them:
var result = {};
for
(var i = 0; i < data.models.length; i++) {
var perm = data.models[i];
for
(var member
in
perm) {
result[
"perms["
+ i +
"]."
+ member] = perm[member];
}
}
return
result;
}
},
batch:
true
,
// enable batch editing - changes will be saved when the user clicks the "Save changes" button
pageSize: 20,
schema: {
model: {
// define the model of the data source. Required for validation and property types.
id:
"PermissionID"
,
fields: {
PermissionID: { editable:
false
, nullable:
true
},
NetLogin:
"User"
,
PayrollTitle:
"Payroll"
,
FunctionTitle:
"Function"
,
Level: { type:
"number"
, validation: { required:
true
, min: 1} }
}
}
}
}});
$(
"#grid"
).kendoGrid({
dataSource: dataSource,
pageable:
true
,
height: 425,
sortable:
true
,
filterable:
true
,
groupable:
true
,
resizable:
true
,
reorderable:
true
,
toolbar: [
"create"
,
"save"
,
"cancel"
],
// specify toolbar commands
columns: [
{ field:
"NetLogin"
, width:
"70px"
, editor: userDropDownEditor },
{ field:
"PayrollTitle"
, width:
"70px"
, editor: payrollDropDownEditor },
{ field:
"FunctionTitle"
, width:
"70px"
, editor: functionDropDownEditor },
{ field:
"Level"
, width:
"70px"
},
{ command:
"destroy"
, title:
"Delete"
, width:
"60px"
, groupable:
false
, filterable:
false
}],
editable:
true
// enable editing
});
});
function userDropDownEditor(container, options) {
$(
'<input data-text-field="NetLogin" data-value-field="NetLogin" data-bind="value:'
+ options.field +
'"/>'
)
.appendTo(container)
.kendoDropDownList({
autoBind:
false
,
dataSource: {
transport: {
read: {
url:
"@Url.Action("
Read
", "
User
")"
,
//specify the URL which should return the records. This is the Read method of the HomeController.
type:
"POST"
//use HTTP POST request as by default GET is not allowed by ASP.NET MVC
}
}
}
});
}
function payrollDropDownEditor(container, options) {
$(
'<input data-text-field="Title" data-value-field="Title" data-bind="value:'
+ options.field +
'"/>'
)
.appendTo(container)
.kendoDropDownList({
autoBind:
false
,
dataSource: {
transport: {
read: {
url:
"@Url.Action("
Read
", "
Payroll
")"
,
//specify the URL which should return the records. This is the Read method of the HomeController.
type:
"POST"
//use HTTP POST request as by default GET is not allowed by ASP.NET MVC
}
}
}
});
}
function functionDropDownEditor(container, options) {
$(
'<input data-text-field="Title" data-value-field="Title" data-bind="value:'
+ options.field +
'"/>'
)
.appendTo(container)
.kendoDropDownList({
autoBind:
false
,
dataSource: {
transport: {
read: {
url:
"@Url.Action("
Read
", "
Function
")"
,
//specify the URL which should return the records. This is the Read method of the HomeController.
type:
"POST"
//use HTTP POST request as by default GET is not allowed by ASP.NET MVC
}
}
}
});
}
</script>
This covers the Read() actions and custom editors, however I need some help in how I translate both the controller code and possibly the view code (I'm not sure?) so that the UserID, PayrollID and FunctionID are passed back to the "Permissions" Model.
Please can someone help?
Andy
P.S.
Here is my controller:
using
System;
using
System.Collections.Generic;
using
System.Data;
using
System.Data.Entity;
using
System.Linq;
using
System.Web;
using
System.Web.Mvc;
using
PayPlate.Models;
using
PayPlate.DAL;
using
PagedList;
namespace
PayPlate.Controllers
{
public
class
PermissionController : Controller
{
UnitOfWork unitOfWork =
new
UnitOfWork();
public
ActionResult Index()
{
return
View();
}
/// <summary>
/// Creates new products by inserting the data posted by the Kendo Grid in the database.
/// </summary>
/// <param name="products">The products created by the user.</param>
/// <returns>The inserted products so the Kendo Grid is aware of the database generated ProductID</returns>
[HttpPost]
public
ActionResult Create(IEnumerable<Permission> perms)
{
var result =
new
List<Permission>();
//Iterate all created products which are posted by the Kendo Grid
foreach
(var permission
in
perms)
{
// Create a new Product entity and set its properties from productViewModel
var perm =
new
Permission
{
User = permission.User,
Payroll = permission.Payroll,
Function = permission.Function,
Level = permission.Level
};
// store the product in the result
result.Add(perm);
// Add the entity
unitOfWork.PermissionRepository.Insert(perm);
}
// Insert all created products to the database
unitOfWork.Save();
// Return the inserted products - the Kendo Grid needs their ProductID which is generated by SQL server during insertion
return
Json(result.Select(p =>
new
Permission
{
PermissionID = p.PermissionID,
User = p.User,
Payroll = p.Payroll,
Function = p.Function,
Level = p.Level
})
.ToList());
}
/// <summary>
/// Reads the available products to provide data for the Kendo Grid
/// </summary>
/// <returns>All available products as JSON</returns>
[HttpPost]
public
ActionResult Read()
{
var perms = unitOfWork.PermissionRepository.Get()
.Select(r =>
new
{ PermissionID = r.PermissionID, UserID = r.UserID, PayrollID = r.PayrollID, FunctionID = r.FunctionID, Level = r.Level, NetLogin = r.User.NetLogin, PayrollTitle = r.Payroll.Title, FunctionTitle = r.Function.Title });
/* var perms = unitOfWork.PermissionRepository.Get()
// Use a view model to avoid serializing internal Entity Framework properties as JSON
.Select(p => new Permission
{
PermissionID = p.PermissionID,
UserID = p.UserID,
PayrollID = p.PayrollID,
FunctionID = p.FunctionID,
Level = p.Level
}).ToList();*/
return
Json(perms);
}
/// <summary>
/// Updates existing products by updating the database with the data posted by the Kendo Grid.
/// </summary>
/// <param name="products">The products updated by the user</param>
[HttpPost]
public
ActionResult Update(IEnumerable<Permission> perms)
{
//Iterate all created products which are posted by the Kendo Grid
foreach
(var permission
in
perms)
{
// Attach the entity
unitOfWork.PermissionRepository.Update(permission);
}
// Save all updated products to the database
unitOfWork.Save();
//Return emtpy result
return
Json(
null
);
}
/// <summary>
/// Destroys existing products by deleting them from the database.
/// </summary>
/// <param name="products">The products deleted by the user</param>
[HttpPost]
public
ActionResult Destroy(IEnumerable<Permission> perms)
{
//Iterate all destroyed products which are posted by the Kendo Grid
foreach
(var permission
in
perms)
{
// Delete the entity
unitOfWork.PermissionRepository.Delete(permission);
}
// Delete the products from the database
unitOfWork.Save();
//Return emtpy result
return
Json(
null
);
}
}
}