Telerik MVC - Numeric textbox in grid editor - asp.net-mvc-3

In my editor for insert telerik show only common textbox (not integer,decimal etc).
this is my view:
#(Html.Telerik().Grid <GamePlayer2>(Model).Name("za11").DataKeys(keys => keys.Add(c => c.Id))
.ToolBar(commands => commands.Insert()
.ButtonType(GridButtonType.ImageAndText))
.DataBinding(dataBinding => dataBinding.Server()
.Insert("PlayerAdd", "Player", new { })
.Update("PlayerUpdate", "Player", new { })
.Delete("PlayerDelete", "Player", new { })
)
.Columns(columns =>
{
columns.Bound(b => b.Name);
columns.Bound(b => b.Price);
columns.Command(commands =>
{
commands.Edit();
commands.Delete();
}).Width(200);
})
.Editable(editing => editing.Mode(GridEditMode.PopUp)))
model:
public class GamePlayer2
{
public int Id { get; set; }
public string Name { get; set; }
[DataType(DataType.Currency)]
public decimal Price{ get; set; }
}
Scripts are registered on _Layout. Where is a problem? Why currency(integer,date etc) textbox won't display for fields?

Make sure you have added the EditorTemplates under the Shared/EditorTemplates folder. Basically they are automatically added if you have used the wizard to create your project. If not create a demo project and copy-paste them from there.

Related

Automapper first IQueryable.ProjectTo projection is too slow

I have Dto classes:
public class PackageDto
{
public MemberDto Receiver { get; set; }
public MemberDto Sender { get; set; }
public DocflowDto Docflow { get; set; }
public DocflowTypeOption DocflowTypeId { get; set; }
public string Code { get; set; }
public Guid? DocGuid { get; set; }
}
public class LightPackageDto
{
public DocflowDto Docflow { get; set; }
public DocflowTypeOption DocflowTypeId { get; set; }
public string Code { get; set; }
public Guid? DocGuid { get; set; }
}
public class MemberDto
{
public string Prop1 { get; set; }
public EntityTypeOption Prop2 { get; set; }
public string Prop3 { get; set; }
public string Prop4 { get; set; }
public string Prop5 { get; set; }
public PersonDto Director { get; set; }
public string CompanyShortName { get; set; }
public string CompanyFullName { get; set; }
public string CompanyPrefix { get; set; }
}
DocflowDto has 3 simple type properties and is projected by flattening.
PersonDto has 3 simple type properties and is projected by flattening too
Mapping rules:
CreateMap<Person, PersonDto>();
CreateMap<Member, MemberDto>()
.ForMember(dest => dest.Prop1, opt => opt.MapFrom(src => src.Employee.Prop1))
.ForMember(dest => dest.Prop2, opt => opt.MapFrom(src => src.Prop2))
.ForMember(dest => dest.Prop3, opt => opt.MapFrom(src => src.Employee.Prop3))
.ForMember(dest => dest.Prop4, opt => opt.MapFrom(src => src.Employee.Prop4))
.ForMember(dest => dest.Prop5, opt => opt.MapFrom(src => src.Employee.Prop5))
.ForMember(dest => dest.Director, opt => opt.MapFrom(src => src.Employee.Director))
.ForMember(dest => dest.CompanyShortName, opt => opt.MapFrom(src => src.Company.CompanyShortName))
.ForMember(dest => dest.CompanyFullName, opt => opt.MapFrom(src => src.Company.CompanyFullName))
.ForMember(dest => dest.CompanyPrefix, opt => opt.MapFrom(src => src.Company.Prefix))
;
CreateMap<Data.Models.Docflow.Package, PackageDto>()
.ForMember(dest => dest.Sender, opt => opt.MapFrom(src => src.Sender))
.ForMember(dest => dest.Receiver, opt => opt.MapFrom(src => src.Receiver))
.ForMember(dest => dest.Docflow, opt => opt.MapFrom(src => src.Docflow))
.ForMember(dest => dest.DocGuid, opt => opt.MapFrom(src => src.Files.FirstOrDefault().DocGuid))
;
CreateMap<Data.Models.Docflow.Package, LightPackageDto>()
.ForMember(dest => dest.Docflow, opt => opt.MapFrom(src => src.Docflow))
.ForMember(dest => dest.DocGuid, opt => opt.MapFrom(src => src.Files.FirstOrDefault().DocGuid));
Then tests:
//fast
var lightEntity = await _db.Packages.Where(p => p.PackageGuid == packageGuid).ProjectTo<LightPackageDto>().FirstOrDefaultAsync();
//fast (_db.GetPackage make query with all necessary includes)
var entity = await _db.GetPackage(packageGuid);
var entityDto = AutoMapper.Mapper.Map<Package, PackageDto>(entity);
//first run too slow
var result = await _db.Packages.AsNoTracking().Where(p => p.PackageGuid == packageGuid).ProjectTo<PackageDto>().FirstOrDefaultAsync();
1) So if I project to LightPackageDto (without Member projections) is all right.
2) If I return entity manually from EF with includes and then I make mappings for "in memory" entity is all right too
3) If I want Automapper makes "Select" query applying ProjectTo I allways get freeze about 2-3 sec. But freeze appears only single first time. Why?
And additional question. I see in result sql select statement all the columns of all the concerning tables. I supposed to see only columns needed for destination projection. Why are all there?
It is just some stupid bug. It is not caching or anything. Because touching the intended projection and canceling the task is enough to "clean the path" (solution 1). Or (sometimes) converting query to list before getting first element also works (solution 2).
Solution 1:
Works every time for me. (Note that the time (1000 ms in this case) starts counting when CancelAfter method is hit. So debugging step-by-step jumps to catch block almost every time.)
CancellationTokenSource cancelationTokenSource = new CancellationTokenSource();
cancelationTokenSource.CancelAfter(1000);
PackageDto result = null;
try
{
result = await _db.Packages.AsNoTracking()
.Where(p => p.PackageGuid == packageGuid).ProjectTo<PackageDto>()
.FirstOrDefaultAsync(cancelationTokenSource.Token);//cancel this, when taking longer than 1s
}
catch (OperationCanceledException)
{ //do absolutely the same thing, but now it will be fast...
result = await _db.Packages.AsNoTracking()
.Where(p => p.PackageGuid == packageGuid).ProjectTo<PackageDto>()
.FirstOrDefaultAsync();
}
Solution 2:
!!! Doesn't work consistently. Need some more investigation
PackageDto result = await _db.Packages.AsNoTracking()
.Where(p => p.PackageGuid == packageGuid).ProjectTo<PackageDto>()
.ToList().FirstOrDefault();//converting to list for some reason helps here..
Yeah. Not the most beautiful solution, but better than waiting 25 seconds...
(btw .net6, Automapper 10.1.1, AutoMapper.Collection.EntityFrameworkCore 7.1.3)

Kendo Pie Chart MVC Data Binding

I'm having an issue with Telerik's Kendo UI Pie Chart in MVC. I can't find any decent code examples on their site. The one demo I've found only shows half of the code, so I tried guessing at how to get it working. I'm getting an error, and no matter what I've tried to eliminate the error, nothing seems to work. It's having an issue with the series.Pie section where you actually bind the data. I copied the code that was in their example, and used the lambda expression just like they did. model => model.Percentage and model => model.StatusName to work with my view model. But it errors out on the very first lambda, with this error message:
CS1660: Cannot convert lambda expression to type 'string' because it is not a delegate type
Here is the relevant code:
ViewModel / View:
public class StatusPercentageViewModel
{
public string StatusName { get; set; }
public int Count { get; set; }
public double Percentage { get; set; }
}
#model IEnumerable<StatusPercentageViewModel>
#(Html.Kendo().Chart(Model)
.Name("StatusBreakdown")
.Legend(legend => legend
.Position(ChartLegendPosition.Bottom)
)
.Series(series =>
{
series.Pie(
model => model.Percentage,
model => model.StatusName,
null,
null
);
})
.Tooltip(tooltip => tooltip.
Template("${ category } - ${ value }%").Visible(true)
)
)
You probably need to specify the model if you want to define your series like that. See this example
For example:
#(Html.Kendo().Chart<StatusPercentageViewModel>()
.Name("StatusBreakdown")
.Legend(legend => legend.Position(ChartLegendPosition.Bottom))
.DataSource(ds => ds.Read(read => read.Action("GetStatus", "Status")))
.Series(series =>
{
series.Pie(
model => model.Percentage,
model => model.StatusName
);
})
.Tooltip(tooltip => tooltip.Template("${ category } - ${ value }%").Visible(true))
)
Another way (more similar to what you have now) to do it would be:
#model IEnumerable<StatusPercentageViewModel>
#(Html.Kendo().Chart()
.Name("StatusBreakdown")
.Legend(legend => legend.Position(ChartLegendPosition.Bottom))
.Series(series => series.Pie(Model))
.Tooltip(tooltip => tooltip.Template("${ category } - ${ value }%").Visible(true))
)

Ajax Binding Telerik MVC Grid with DetailView in one call

I have the following markup.
#(Html.Telerik().Grid(Model)
.Name("Grid")
.DataKeys(keys => keys.Add(key => key.Id))
.Columns(columns =>
{
columns.Bound(c => c.FullNameWithEmail).ClientTemplate("<#= FullNameWithEmail #>").Title("Name and Email").Width(230);
columns.Bound(c => c.Notes);
})
.ClientEvents(events => events.OnRowDataBound("grid_onRowDataBound"))
.DetailView(checkInAppGridDetails => checkInAppGridDetails.ClientTemplate("<# if (RelatedCount > 0) { #>" +
Html.Telerik().Grid<ViewModel>()
.Name("GridDetails_<#= Id #>")
.Footer(false)
.Columns(columns =>
{
columns.Bound(c => c.FullNameWithEmail).ClientTemplate("<#= FullNameWithEmail #>").Title("Name and Email").Width(225);
columns.Bound(c => c.Notes);
columns.Bound(c => c.Actions).ClientTemplate("<#= Actions #>").Width(150);
})
.ClientEvents(events => events.OnRowDataBound("GridDetails_onRowDataBound"))
.DataBinding(dataBinding => dataBinding.Ajax()
.Select("GetRelated", "Controller", new
{
id = #ViewBag.EventKey,
ticketId = "<#= Id #>"
}))
.ToHtmlString() +
"<# } #>"
))
)
What i have here is that i am binding the main grid with Ajax call, and once rows got bound the details view gets bound with the DataBinding ajax call.
I already have in the Model a collection for the related records i wanted to show in the DetailView, i don't want the extra call to the server.
here is an example of the ViewModel
public class ViewModel
{
public string FirstProperty {get; set;}
.
.
.
public IEnumurable<ViewModel> RelatedRecords { get; set; }
}
Any idea how to bind the whole Grid with the DetailView with only single Ajax request?
Just used telerik support example to fix this, and it worked very well.Telerik Post

MVCContrib Grid - Show carriage returns

How do you show carriage returns inside a MVCContrib Grid? I've tried replacing the returns with "<br>", however that is actually showing a <br> in my display "test<br>test"
<div id="noteList">
#Html.Grid(Model).Columns(column => {
column.For(x => x.TimeStamp);
column.For(x => x.UserName);
column.For(x => x.Note.Replace("\r\n","\"<br>\"")).Named("Note");
}).Attributes(Style => "text-aligh: center", #Class => "linkGrid")
</div>
Is there a way to get the browser to render the original return's "\r\n"?
You could use a custom column:
column.Custom(item => #item.Note.Replace("\r\n", "<br/>")).Named("Note");
But a safer and IMHO a more robust solution would be to use a custom HTML helper:
public static class HtmlExtensions
{
public static IHtmlString FormatNote(this HtmlHelper html, string note)
{
if (string.IsNullOrEmpty(note))
{
return MvcHtmlString.Empty;
}
var lines = note.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
return MvcHtmlString.Create(string.Join("<br/>", lines.Select(x => html.Encode(x))));
}
}
and then:
column.Custom(item => Html.FormatNote(item.Note)).Named("Note");

Server-side Validation using MVC 3

I'm building an ASP.NET MVC3 app. I have 2 views;
List item contains a grid
details view consists of a drop down list (combobox)
I have a requirement to alert the user at the details view when they try to select item was previously selected in the list view. In other words, the grid should contain unique items
What is the best way to implement a server-side business logic validation?
Model:
public class AllocatedResource
{
public virtual Project Project { get; set; }
public virtual DateTime StartDate { get; set; }
public virtual DateTime EndDate { get; set; }
}
List View:
#(Html.Telerik().Grid(Model.AllocatedResources)
.Name("gridAllocatedProject")
.DataKeys(keys =>{keys.Add(p => p.Id);})
.Columns(columns =>
{
columns.Bound(p => p.Id).Visible(false);
columns.Bound(p => p.Project.Name);
columns.Bound(p => p.Project.ProjectManager).Title("Project Manager");
columns.Bound(p => p.StartDate).Width(80).Format("{0:d}");
columns.Bound(p => p.EndDate).Width(80).Format("{0:d}");
})
Details View:
#Html.Label("Project: ")
#(Html.Telerik().ComboBox().Name("Project")
.BindTo(new SelectList(Model.AllProjects, "Id", "Name"))
.Value(Model.AllocatedResource.Project.Id.ToString()))
#Html.Label("Start Date: ")
#(Html.Telerik().DatePicker().Name("StartDate")
.Value(Model.AllocatedResource.StartDate))
#Html.Label("End Date: ")
#(Html.Telerik().DatePicker().Name("EndDate")
.Value(Model.AllocatedResource.EndDate))

Resources