I have the Upload control in an EditorTemplate as follows:
/Views/Letter/EditorTemplates/LetterAttachmentsManage.cshtml:
@using DACRL.Portal.ColorAdmin.Controllers
@using DACRL.Portal.ColorAdmin.Extensions
@model Guid?
@{
string[] extensions = { ".jpg", ".png", ".pdf", ".ppt", ".pptx", ".doc", ".docx", ".xls", ".xlsx" };
}
@Html.HiddenFor(m => m)
<kendo-upload name="letterFiles" multiple="true">
<async save-url="@Url.Action(nameof(UploadController.ChunkSave), ControllerExtensions.Nameof<UploadController>())"
remove-url="@Url.Action(nameof(UploadController.Remove), ControllerExtensions.Nameof<DashboardController>())"
auto-upload="true"
chunk-size="11000" />
<validation allowed-extensions="@extensions" max-file-size="36700160" />
</kendo-upload>
This template is placed within a form on a parent view as
/Views/Letter/Create.cshtml:
@model LetterModel
@using (Html.BeginForm("", "Letter", FormMethod.Post))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(m => m.IdCode)
<div class="panel mt-20px" data-sortable-id="ui-widget-16">
<div class="panel-heading bg-da-blue text-white">
<h4 class="panel-title">RL Info</h4>
</div>
<div class="panel-body">
@Html.EditorFor(m => m, "Letter")
</div>
</div>
<div class="panel mt-20px" data-sortable-id="ui-widget-16">
<div class="panel-heading bg-da-blue text-white">
<h4 class="panel-title">Attachments</h4>
</div>
<div class="panel-body">
@Html.EditorFor(m => m.IdCode, "LetterAttachmentsManage")
</div>
</div>
<div class="row mt-3">
<div class="col-md-1">
<button type="submit" class="btn btn-primary w-100 me-5px" formaction="CreateSave" title="@(Model.IsUpdateCase ? "Update letter" : "Save letter")">@(Model.IsUpdateCase ? "Update" : "Save")</button>
</div>
<div class="col-md-1">
<button type="submit" class="btn btn-default w-100" formaction="CreateSubmit" title="@(Model.IsUpdateCase ? "Update letter & submit" : "Save letter & submit")">Submit</button>
</div>
</div>
}
I'm trying to handle the File logic separately so I have the Upload Controller:
public class UploadController : BaseControllerWithAuth<UploadController>
{
private readonly IWebHostEnvironment hostEnvironment;
public UploadController(IWebHostEnvironment hostingEnvironment, IHttpContextAccessor httpContextAccess, IUserService userService) : base(httpContextAccess, userService) => hostEnvironment = hostingEnvironment;
public async Task<ActionResult> ChunkSave([Bind(Prefix = "IdCode.letterFiles")] IEnumerable<IFormFile>? letterFiles, string? metaData, Guid? idCode)
{
try
{
if (metaData == null)
return await Save(letterFiles);
var chunkData = JsonSerializer.Deserialize<ChunkMetaDataModel>(metaData)!;
if (letterFiles != null)
{
foreach (var file in letterFiles) AppendToFile(Path.Combine(hostEnvironment.WebRootPath, Constants.FileUploadPath, chunkData!.FileName), file, idCode?.ToString());
}
var fileBlob = new FileResultModel
{
uploaded = chunkData!.TotalChunks - 1 <= chunkData.ChunkIndex,
fileUid = chunkData.UploadUid
};
return Json(fileBlob);
}
catch (Exception ex)
{
Logger.LogError(ex, $"{nameof(UploadController)} => {nameof(ChunkSave)}: Error: {ex.Message}");
throw;
}
}
public ActionResult Remove(string[]? fileNames)
{
try
{
if (fileNames == null) return Content("");
foreach (var fullName in fileNames)
{
var fileName = Path.GetFileName(fullName);
var physicalPath = Path.Combine(hostEnvironment.WebRootPath, Constants.FileUploadPath, fileName);
if (System.IO.File.Exists(physicalPath)) System.IO.File.Delete(physicalPath);
}
return Content("");
}
catch (Exception ex)
{
Logger.LogError(ex, $"{nameof(UploadController)} => {nameof(Remove)}: Error: {ex.Message}");
throw;
}
}
private void AppendToFile(string fullPath, IFormFile content, string? idCode)
{
try
{
var basePath = Path.Combine(hostEnvironment.WebRootPath, Constants.FileUploadPath);
if (!Directory.Exists(basePath)) Directory.CreateDirectory(basePath);
var letterPath = Path.Combine(basePath, idCode!);
if (!Directory.Exists(letterPath)) Directory.CreateDirectory(letterPath);
using var stream = new FileStream(fullPath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
content.CopyTo(stream);
}
catch (IOException ex)
{
Logger.LogError(ex, $"{nameof(UploadController)} => {nameof(AppendToFile)}: Error: {ex.Message}");
throw;
}
catch (Exception ex)
{
Logger.LogError(ex, $"{nameof(UploadController)} => {nameof(AppendToFile)}: Error: {ex.Message}");
throw;
}
}
private async Task<ActionResult> Save([Bind(Prefix = "IdCode.letterFiles")] IEnumerable<IFormFile>? letterFiles)
{
try
{
if (letterFiles == null) return Content("");
foreach (var file in letterFiles)
{
var fileContent = ContentDispositionHeaderValue.Parse(file.ContentDisposition);
var fileName = Path.GetFileName(fileContent.FileName!.Trim('"'));
var physicalPath = Path.Combine(hostEnvironment.WebRootPath, Constants.FileUploadPath, fileName);
await using var fileStream = new FileStream(physicalPath, FileMode.Create);
await file.CopyToAsync(fileStream);
}
return Content("");
}
catch (Exception ex)
{
Logger.LogError(ex, $"{nameof(UploadController)} => {nameof(Save)}: Error: {ex.Message}");
throw;
}
}
}
Note: Due to this being an EditorTemplate, I had to add the
[Bind(Prefix = "IdCode.letterFiles")]
Now, once the file is being chunked back to the Controller's ChunkSave action, I need to get the value of the model of this EditorTemplate as it will correlate with the primary entity later.
I have tried adding a parameter to the Controller's ChunkSave action as Guid? idCode. But I always get a null there.
How do I go about this dilemma?
I'm not using Newtosoft.Json anymore so I tried to deserialize the metadata like this:
var chunkData = JsonSerializer.Deserialize<ChunkMetaDataModel>(metaData)!;
It's not getting de-serialized properly as all strings are null and all integers are 0s.
Please update this documentation page: ASP.NET Core Upload Component Chunk Upload | Telerik UI for ASP.NET Core & this demo: Chunk Upload in ASP.NET Core Upload Component Demo | Telerik UI for ASP.NET Core soon as I'm stuck for now.
I originally got help from StackOverflow from my question: c# - System.Text.Json.* & deserialization of streams - Stack Overflow
This question is two-fold, and I can't seem to find the answers in the documentation. For background info, I'm using the latest version of Wizard (the Tag version) :
TIA!
Hi All,
This example of a responsive form is not working. The columns never collapse and stack. They are aways 2 columns.
I have tried many other things also but nothing seems to work.
I am using TagHelpers FYI
Update: I also tried the TagHelpers sample and it does not work either.
Is it possible to get a Respond kendo-form that has 2, 3, or 4 columns in desktop but collapse to 1 column on mobile?
Thanks
Thanks
I'm using the Grid component (ASP.NET Core Razor Pages).
I would like a column that when clicked will navigate to a specified Page within my application, passing along with it one or more of the column values in my model.
Ideally I'd like to avoid Templates, because it just seems like a lot of string to manage to get an HTML output that I like.
I did come across Commands with a custom Click, but I haven't been able to find documentation yet that shows how I can pass the row details along so I can access specific column values to use in a redirect via JavaScript.
I did get this working with
columns.Template("my anchor tag html goes here with template syntax for #:SomePropValue#")
But it doesn't come across as "clean" as I'd like.
So I'm hoping there's some way to access/pass along a given row's column values in a custom click so I can just use JS for a redirect?
columns.Command(action => {action.Custom("View Application").Click("myJavaScriptFunction")
If there's also a way to do this by using only Html Helpers/Razor syntax, I'm also okay with that! But I couldn't find what I'm looking for with just that either, so I started looking into custom clicks and JS.
HI
The SelectListItemBuilder's HtmlAttributes property of DropDownList was gone, WHY ???
namespace Kendo.Mvc.UI.Fluent
{
 public class SelectListItemBuilder : IHideObjectMembers
 {
Everyone needs HtmlAttributes property.
*Kendo.Mvc, Version=2021.3.1207.0。
(telerik.ui.for.aspnet.core\2021.3.1207\lib\net6.0\Kendo.Mvc.dll)
Best regards
Chris
I have a PanelBar control with 3 panels, each holding a Chart control with column items. I am using the HtmlHelper build the charts. The PanelBar is in a container that spans 100% of the screen. By default, the charts in the panels render at about 25% of the width - and that means charts with a lot of categories are seriously compressed and unreadable.
I've tried using the Width option of ChartArea (inside Chart), and while that works, I can't always be sure the double I set this to will be right for all user's browsers. There is no string option, so Width has to be a number of pixels.
Using HtmlAttributes (adding style) also has no effect.
How can I get the charts to occupy 100% of the container other than just guessing using ChartArea's Width or resorting to JavaScript to redraw the chart after the page is rendered?
hi, I have a simple grid set up for data entry in batch mode. The users don't like having to take their fingers off the keyboard and use the mouse to click a button to either start a new entry or save the changes in the current row. Hitting the Enter key doesn't do anything. Is there a keystroke available that would save the changes in the current row without having to click the Save button?
Similarly, is there a keystroke that would start a new record entry?
If not, any ideas for implementing something like this?
many thanks,
Yvette
I have the below tabstrip and on a button click I am trying to select/activate the second tab programatically. Actually, I can't get it to select/activate any tabe programatically. Below my tabstrip definition below I have listed all of the things I have tried but, none of these seem to work. I am using Visual Studio 2022 and Telerik.UI.for.AspNet.Core 2022.2.510. What am I doing wrong?
@(Html.Kendo().TabStrip()
.Name("tabMain")
.Animation(animation =>
animation.Open(effect =>
effect.Fade(FadeDirection.In)))
.Items(tabstrip =>
{
tabstrip.Add().Text("Table Status")
.HtmlAttributes(new { id="tabMain-tab-1", name="tabMain-tab-1"})
.Selected(true)
.Content(@<text>
<div>
</div>
</text>);
tabstrip.Add().Text("Filters")
.HtmlAttributes(new { id="tabMain-tab-2", name="tabMain-tab-2"})
.Content(@<text>
<div>
</div>
</text>);
tabstrip.Add().Text("Bill List")
.HtmlAttributes(new { id="tabMain-tab-3", name="tabMain-tab-3" })
.Content(@<text>
<div>
</div>
</text>);
tabstrip.Add().Text("Main Data")
.HtmlAttributes(new { id="tabMain-tab-4", name="tabMain-tab-4" })
.Content(@<text>
<div>
</div>
</text>);
tabstrip.Add().Text("Details")
.HtmlAttributes(new { id="tabMain-tab-5", name="tabMain-tab-5" })
.Content(@<text>
<div>
</div>
</text>);
tabstrip.Add().Text("Reports")
.HtmlAttributes(new { id="tabMain-tab-6", name="tabMain-tab-6" })
.Content(@<text>
<div>
</div>
</text>);
tabstrip.Add().Text("Export")
.HtmlAttributes(new { id="tabMain-tab-7", name="tabMain-tab-7" })
.Content(@<text>
<div>
</div>
</text>);
})
)
I have tried all of the following but, none of these seem to work.
$("#tabMain").kendoTabStrip().data("kendoTabStrip").select(2);
$("#tabMain").kendoTabStrip().select(2);
$("#tabMain").kendoTabStrip().data("kendoTabStrip").activateTab(2);
$("#tabMain").kendoTabStrip().activateTab(2);
var tabToActivate = $("#tabMain-tab-2");
$("#tabMain").kendoTabStrip().data("kendoTabStrip").activateTab(tabToActivate);
var tabToActivate = $("#tabMain-tab-2");
$("#tabMain").kendoTabStrip().activateTab(tabToActivate);
var tabStrip = $("#tabMain").kendoTabStrip().data("kendoTabStrip");
tabStrip.select("li:1");
var tabStrip = $("#tabMain").kendoTabStrip().data("kendoTabStrip");
tabStrip.select(1);
var tabStrip = $("#tabMain").kendoTabStrip().data("kendoTabStrip");
tabStrip.select((tabStrip.tabGroup.children("li").length - 5));
var tabStrip = $("#tabMain").data("kendoTabStrip");
tabStrip.select((tabStrip.tabGroup.children("li").length - 5));
var tabStrip = $("#tabMain").kendoTabStrip().data("kendoTabStrip");
tabStrip.activateTab((tabStrip.tabGroup.children("li").length - 5));
var tabStrip = $("#tabMain").data("kendoTabStrip");
tabStrip.activateTab((tabStrip.tabGroup.children("li").length - 5));
var tabStrip = $("#tabMain").kendoTabStrip().data("kendoTabStrip");
tabStrip.select(1);
Inspecting the tab I want to select I see:
<li class="k-state-default k-item k-tabstrip-item" id="tabMain-tab-2" name="tabMain-tab-2" role="tab" aria-controls="tabMain-2"><span class="k-loading k-complete"></span><span class="k-link" unselectable="on">Filters</span></li>Hello,
I found something but I don't know whether this is a bug.
When I installed the latest version (2022.2.802) I saw some unwanted references in the package like MVC.Core 2.1.0. They belong to ASP.NET Core 2.1.0. Because of that, I can't use some extension methods like UseStaticFiles.