Custom grid using Telerik pluggin in nopcommerce 2.8 - asp.net-mvc

Iam working on nopcommerce2.8 version. I have a problem with telerik plugin implementation to create new grid.
Iam implementing a concept where for a product i want to give different price for different customer. So to assign new price for different customers, in admin panel i am creating a grid in edit productvariant page using telerik. I have created a new tab to display these details. Iam able to display customer name and price in grid, but i am not able to call update function, when i click on update button after editing a row. The same update function i called for Deleting the grid row also, so when i click on delete the same update function getting trigger. I think some setting has been missed in View. Please help me to solve this update issue.
The model, view and controller of my nopcommerce in given below.
Thanks.
//Model
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
using FluentValidation.Attributes;
using Nop.Admin.Models.Customers;
using Nop.Admin.Validators.Catalog;
using Nop.Web.Framework;
using Nop.Web.Framework.Localization;
using Nop.Web.Framework.Mvc;
using Telerik.Web.Mvc;
namespace Nop.Admin.Models.Catalog
{
public partial class CustomerProductPriceModel : BaseNopModel
{
public int Customer_Id { get; set; }
[NopResourceDisplayName("Customer Name")]
public string Customer_name { get; set; }
[NopResourceDisplayName("Price")]
public decimal Price { get; set; }
[NopResourceDisplayName("Unit")]
public string Units { get; set; }
}
}
// view
#(Html.Telerik().Grid<CustomerProductPriceModel>()
.Name("Grid")
.DataKeys(x =>
{
x.Add(y => y.Customer_Id);
})
.DataBinding(dataBinding =>
{
dataBinding.Ajax()
.Select("CustomerProductPriceList", "ProductVariant", new { productVariantId = Model.Id })
.Update("CustomerPriceUpdate", "ProductVariant", new { productVariantId = Model.Id })
.Delete("CustomerPriceUpdate", "ProductVariant", new { productVariantId = Model.Id });
})
.Columns(columns =>
{
columns.Bound(y => y.Customer_name).Width(200).ReadOnly();
columns.Bound(y => y.Price).Width(100);
columns.Command(commands =>
{
commands.Edit().Text(T("Admin.Common.Edit").Text);
commands.Delete().Text(T("Admin.Common.Delete").Text);
}).Width(180);
})
.Editable(x =>
{
x.Mode(GridEditMode.InLine);
})
.EnableCustomBinding(true)
)
// controller
[GridAction(EnableCustomBinding = true)]
public ActionResult CustomerPriceUpdate(GridCommand command, CustomerProductPriceModel model, int productVariantId)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog))
return AccessDeniedView();
return CustomerProductPriceList(command, productVariantId);
}
[HttpPost, GridAction(EnableCustomBinding = true)]
public ActionResult CustomerProductPriceList(GridCommand command, int productVariantId)
{
if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog))
return AccessDeniedView();
var productVariant = _productService.GetProductVariantById(productVariantId);
if (productVariant == null)
throw new ArgumentException("No product variant found with the specified id");
var CustomerPrices = PrepareCustomerProductPriceModel(productVariant.Product.Id);
var CustomerPricesa = CustomerPrices
.Select(x =>
{
return new CustomerProductPriceModel()
{
Customer_Id = x.Customer_Id,
Price = x.Price,
Units = x.Units,
Customer_name = x.Customer_name
};
})
.ToList();
var model = new GridModel<CustomerProductPriceModel>
{
Data = CustomerPricesa,
Total = CustomerPrices.Count
};
return new JsonResult
{
Data = model
};
}

Is there a reason not to use the built-in customer price levels already in place in nopCommerce, or are you wanting to display all prices at once?

Related

A specified Include path is not valid. The EntityType does not declare a navigation property with the name

The code I have below works. It's pulls in a list of every item in my One Repository.
When I add my second table to pull all the items out of THAT table I get the following error, on my DataTwo I can't figure out why it's throwing this error as the first one is programmed the exact same way.
"A specified Include path is not valid. The EntityType does not declare a navigation property with the name"
View Model
public IList<OneVM> Ones { get; set; }
public IList<TwoVM> Twos { get; set; }
public ViewModelVM()
{
this.Ones = new List<OneVM>();
this.Twos = new List<TwoVM>();
}
Working Original Code Below (Controller)
public ActionResult Directory()
{
var vm = new ViewModelVM();
var datas = _OneRepository.GetData();
vm.Datas = _mapper.Map<IList<DataVM>>(datas.OrderBy(i => i.Name));
return View(vm);
}
Desired Broken Code Below (Controller)
public ActionResult Directory()
{
var vm = new FormDirectoryVM();
var datas = _OneRepository.GetData();
var datasTwo= _TwoRepository.GetMoreData();
vm.Datas = _mapper.Map<IList<DataVM>>(datas.OrderBy(i => i.Name));
return View(vm);
vm.DatasTwo= _mapper.Map<IList<DataTwoVM>>(datasTwo);
return View(vm);
}
The problem was my Repository. I was including something that didn't need to be.
public IEnumerable<Two> GetMoreData()
{
return _context.Twos
.Include(i => i.Title) // I don't need this line
.Include(i => i.Description) // I don't need this line either
.Include(i => i.Keywords)
.Include(j => j.Text) // Or this Line
.Where(i => !i.IsDeleted)
;
}

An item with the same key has already been added when loading Kendo MVC Grid

I am trying to populate a Kendo mvcGrid and I keep getting the error An item with the same key has already been added.
I have seen elsewhere that duplicate model properties is the likeliest source of the problem but I have no duplicate properties in my model. I've even simplified everything to just a basic mock up to eliminate as many possible variables as possible..and I cant get the grid to load data.
I've tried it as a Html.Partial where its not loaded initially because of a empty model and then loading it through jquery...Ive tried with passing in am empty model so that the grid will load initially without data and then doing a datasource refresh...no luck there either. Basically as soon as I try to add content to the grid with a populated model I get the error and no data is loaded.
Been fighting this issue for 2 days now and had no luck. Ill post my code here maybe someone else can see what I'm missing.
One variable that cant change is the grid resides on a partial view with a model different from its parent view.
in the parent view I have tried both
<div id ="columnkgrid">#{Html.RenderPartial("Columns", new TestFieldIssue.Models.FieldListModel());}</div>
and
<div id="columnkgrid">#Html.Partial("Columns", new TestFieldIssue.Models.FieldListModel())</div>
either way will succeed in posting a grid with no data..it has no data yet because its populated by the selection of a value in a dropdown list.
so as to not over complicate the sample I've just set a hard coded value in the jquery function I have been using to refresh the grid.
function loadgrid() {
var grid = $("#grid").data("kendoGrid");
var val = 1;
grid.dataSource.read({ table_pk: val });
grid.refresh();
}
the grid code in the partial once again kept it simple without any bells and whistles just to test.
#(Html.Kendo().Grid(Model.fields)
.DataSource(data => data
.Ajax()
.Model(model => model.Id(m => m.field_pk))
.Read(r => r.Action("Columns","Home"))
)
.Name("grid")
.Columns(c =>
{
c.Bound(m => m.field_name).Title("Field Name").Width(100);
})
)
and the controller methods loading some mock data
public ActionResult Columns(int? table_pk)
{
FieldListModel model;
if (table_pk == null)
{
model = GetEmptyColumns();
}
else
{
model = GetColumns();
}
return PartialView("Columns", model);
}
public FieldListModel GetColumns()
{
FieldListModel model = new FieldListModel();
model.fields = new List<FieldModel>();
model.fields.Add(new FieldModel { field_name = "field1", field_pk = 1 });
model.fields.Add(new FieldModel { field_name = "field2", field_pk = 2 });
model.fields.Add(new FieldModel { field_name = "field3", field_pk = 3 });
return model;
}
public FieldListModel GetEmptyColumns()
{
FieldListModel model = new FieldListModel();
model.fields = new List<FieldModel>();
model.fields.Add(new FieldModel { field_name = "", field_pk = 0 });
return model;
}
and a very simple Model
public class FieldListModel
{
public List<FieldModel> fields { get; set; }
}
public class FieldModel
{
public int field_pk { get; set; }
public string field_name { get; set; }
}
I made few changes to run your code (correct version of Kendo and JQuery). May be those related to setup at my machine. I was able to reproduce the problem.
Then I changed the action code and was able to see the values populated in Grid:
public ActionResult Columns(int? table_pk, [DataSourceRequest] DataSourceRequest request)
{
FieldListModel model;
if (table_pk == null)
{
model = GetEmptyColumns();
}
else
{
model = GetColumns();
}
return Json(model.fields.ToDataSourceResult(request));
}
The change is accepting an additional parameter in action method of type DataSourceRequest. The Kendo grid wraps request in this object to specify sorting and paging information. The grid itself gets updated with data wrapped under DataSourceRequest object (note in return statement). More information here.

How to make Sorting and Filtering working for viewmodel column in InLine editing of Kendo UI MVC grid signalR?

Sorting and Filtering are not working on the column bound with ViewModel entity. It is working fine with other columns.
Sample Grid Code:
#(Html.Kendo().Grid<abc.Models.ShippingViewModel>()
.Name("ShippingGrid")
.Columns(c =>
{
c.Bound(m => m.Id).Hidden();
c.Bound(m => m.LocationViewModel)
.ClientTemplate("#=LocationViewModel.LocationName#")
.Title("Pickup Location")
.HeaderHtmlAttributes(new { #title = "Pickup Loactions" });
c.Bound(m => m.UnitsShipped)
.HtmlAttributes(new { style = "text-align:right" })
.HeaderHtmlAttributes(new { title = "Units Shipped", style = "text-align: right" });
Model:
public class InHouseShippingViewModel
{
[ScaffoldColumn(false)]
public int Id { get; set; }
[Required]
[UIHint("ShippingLocationEditor")]
public LocationViewModel LocationViewModel { get; set; }
[Required]
[Display(Name = "Units Shipped")]
[UIHint("ComanexIntegerEditor")]
[DisplayFormat(DataFormatString = GlobalVaribleDeclarations.displayFormatForInteger)]
public int UnitsShipped { get; set; }
}
Hub/Controller code:
public IEnumerable<ShippingViewModel> Shipping_Read()
{
var queryResult = ShippingRepository.Shipping_Read();
return queryResult;
}
Here Sorting is working fine on "UnitShipped" column whereas it is not working on "LocationViewModel" column. If I use c.Bound(m => m.LocationViewModel.LocationName), sorting & filtering are working fine but then I am not able to get the DropDownEditor for the this column when editing a record. I am using "InLine" editing here.
I have tested this with "PopUp" editing and everything working fine. I would like to achieve this with "InLine" editing though.
Please advise what should I do to achieve "InLine" editing with Cascading dropdown and Sorting all together. thanks!
there is a mix of things to do. First for filtering etc you need to use the datasourcerequest parameter as in normal ajax calls but then you will find out that sorting does not work.
public DataSourceResult Read(MyDataSourceRequest request)
{
}
this does not work since the kendo regular use 'sorts' for passing a collection of sort and this collection is passed by the signalr datasource as 'sort' (no s). you will have to use the dynamic linq nuget package which has a custom datasource request that will work with signalr. Please copy their code in your solution for the custom datarequest object and the slightly todatasourceresult syntax.
http://www.telerik.com/forums/problems-with-grid-using-signalr-and-serverfiltering-sorting-and-paging
relaying information needs a wrap in datasourceresult as well
Clients.Others.update(WrapInDataSourceResult(item));
public DataSourceResult WrapInDataSourceResult(EmployeeViewModel item)
{
return new DataSourceResult
{
Data = new[]
{
item
}
};
}
also you need to activate server side options serverpaging(true) etc
.SignalR()
.AutoSync(true)
.Sort(c => c.Add(e => e.FullName).Ascending())
.ServerAggregates(true)
.ServerPaging(true)
.ServerSorting(true)
.ServerGrouping(true)
and in the schema
.Schema(schema => schema
.Data("Data")
.Total("Total")
.Aggregates("Aggregates")
.Groups("Groups")
.Model(model =>
{
model.Id(m => m.EmployeeId);
})

How to set the default value for Html.DropDownListFor in MVC

i have following code :
controller method:
public ActionResult Register(int? registrationTypeId)
{
IEnumerable<AccountType> accountTypes = new List<AccountType>
{
new AccountType
{
AccountTypeId = 1,
AccountTypeName = "Red"
},
new AccountType
{
AccountTypeId = 2,
AccountTypeName = "Blue"
}
};
// I want to select account type on registrationTypeId
ViewBag.AccountTypes = accountTypes;
return View();
}
View
<div class="col-md-10">
#Html.DropDownListFor(n => n.AccountType,
new SelectList(ViewBag.AccountTypes, "AccountTypeId", "AccountTypeName"), new { #class = "form-control" })
</div>
Model
public class RegisterViewModel
{
[Required]
[Display(Name = "Account Type")]
public int AccountType { get; set;
}
As you can see registrationTypeId in controller , i want to set the type on its bases if it is not null ,otherwise set to red. I have tried a alot but nothing worked for me. Any help will be appreciated !
I would highly recommend that you don't pass your list through the view bag. have seen too many questions where that has caused major issues. add this to your model
public List<SelectListItem> AccountTypes { get; set; }
in your controller in the get method set your default and set your list
Model.AccountType = 1; // change the one to your default value
Model.AccountTypes = accountTypes; //instead of ViewBag.AccountTypes = accountTypes;
then on your view
#Html.DropDownListFor(x => x.AccountType, Model.AccountTypes)
setting AccountType before passing the model to the view will set the default and the selected value on the view will be passed back in that same value.
The Wrong Way To Do This
var accountTypes = new SelectList(accountTypes, "AccountTypeId", "AccountTypeName");
foreach(var item in accountList)
if (item.AccountTypeId == registrationTypeId)
item.Selected = true;
ViewBag.AccountTypes = accountTypes;
In view,
#Html.DropDownListFor(n => n.AccountType, (SelectList)ViewBag.AccountTypes)

Understanding how strongly typed html helper works

Framework: ASP.NET MVC 3
Tools: VS 2012
Hi guys,
I'm new to ASP.NET mvc, I have been using strongly typed html helper for some time,I don't understand them completely but know that it can provide type checking and keeps name according to property name,after using it for many times I faced this error constantly and dont seem to have any hint why its occuring tried several google searches but none helped me.
Error:
The name 'm' does not exist in the current context
Code:
#Html.LabelFor(m => m.OrginalCont.Title)
But this line of code works perfectly fine.
#Html.TextBox("origTitle", Model.OrginalCont.Title, new { #readonly = "", #class = "text-rounded", style = "width:425px" })
Can someone tell me whats going on here.I have used the same m => m.Name syntax several times in view but they are all working fine.
Update:
Alright I will try to post more code,but as the code may get too long I will try to keep it short and will post code which is related to the problem.
View
#model TS.MOP.Interface.Models.ProjectTranslationModel
<div class="form-item">
#Html.LabelFor(model => model.OrginalCont.Title)
<div class="editor-field">
#Html.TextBox("origTitle", Model.OrginalCont.Title, new { #readonly = "", #class = "text-rounded", style = "width:425px" })
</div>
</div>
Model
public class ProjectTranslationModel
{
public int ProjectId { get; set; }
[Required(ErrorMessageResourceType = typeof(Names), ErrorMessageResourceName = "Required_ErrorMessage")]
[DataType(DataType.Text)]
[Display(ResourceType = typeof(Names), Description = "TranslateLangs_Description", Name = "TranslateLangs_Title")]
public List<SelectListItem> TranslatableLangSelect { get; set; }
public TranslatableLanguageEditor TranslatableLangEditor { get; set; }
public OriginalContent OrginalCont { get; set; }
}
Controller
[Authorize]
public ActionResult TranslationEdit(int? id)
{
if (id.HasValue && User.IsInRole("ContentTranslator"))
{
var model = new ProjectTranslationModel();
model.ProjectId = id.Value;
var ContentTypeId = 2;//Project Page
Guid _currentUserId = Guid.Parse(Membership.GetUser(User.Identity.Name).ProviderUserKey.ToString());
var translatorSettings = db.TranslatorSettings.Where(x => x.UserId == _currentUserId).ToList();
model.TranslatableLangEditor = new TranslatableLanguageEditor();
var list = new List<SelectListItem>();
//Original Text
var originalContent = db.Projects.Where(x => x.Id == id.Value)
.Select(d => new OriginalContent { Title = d.Title, Content = d.Description, ContentCultureId = d.ProjectType.ContentCultureId }).FirstOrDefault();
model.OrginalCont = originalContent;
foreach (var item in translatorSettings)
{
//Select List
var li = new SelectListItem();
if (item.ContentCultureId != originalContent.ContentCultureId)//Dont add the Original Content CultureId to the dropDown
{
li.Value = item.ContentCultureId.ToString();
li.Text = item.ContentCulture.Description;
list.Add(li);
}
}
model.TranslatableLangSelect = list;
return View(model);
}
else
{
return View("Index");
}
}

Resources