I have 2 projects inside the same solution. My first project is a client-side project that has the Upload .razor file. And my second project is a server-side project that has the API Controller. So when I want to upload a file, the file doesn't finish successfully cause the API Call fails with error 404.
I would like to share both codes
1- .razor File:
@page "/"
@inject NavigationManager NavigationManager
<TelerikUpload SaveUrl="@SaveUrl" RemoveUrl="@RemoveUrl" SaveField="file"
AllowedExtensions="@( new List<string>() { ".jpg", ".png", ".jpeg" } )"
MaxFileSize="2048000" MinFileSize="1024" Multiple="false" />
@code {
public string SaveUrl => ToAbsoluteUrl("api/upload/save");
public string RemoveUrl => ToAbsoluteUrl("api/upload/remove");
public string ToAbsoluteUrl(string url)
{
return $"{NavigationManager.BaseUri}{url}";
}
}
2- APIController
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace TelerikBlazorApp2.Server.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class UploadController : Controller
{
public IWebHostEnvironment HostingEnvironment { get; set; }
public UploadController(IWebHostEnvironment hostingEnvironment)
{
HostingEnvironment = hostingEnvironment;
}
[HttpPost]
public async Task<IActionResult> Save(IFormFile file) // the form field name. See SaveField
{
if (file != null)
{
try
{
//foreach (var file in files)
//{
var fileContent = ContentDispositionHeaderValue.Parse(file.ContentDisposition);
// Some browsers send file names with full path.
// We are only interested in the file name.
var fileName = Path.GetFileName(fileContent.FileName.ToString().Trim('"'));
var physicalPath = Path.Combine(HostingEnvironment.ContentRootPath, fileName);
// Implement security mechanisms here - prevent path traversals,
// check for allowed extensions, types, size, content, viruses, etc.
// this sample always saves the file to the root and is not sufficient for a real application
using (var fileStream = new FileStream(physicalPath, FileMode.Create))
{
await file.CopyToAsync(fileStream);
}
// }
}
catch (Exception ex)
{
// implement error handling here, this merely indicates a failure to the upload
Response.StatusCode = 500;
await Response.WriteAsync("some error message"); // custom error message
}
}
// Return an empty string message in this case
return new EmptyResult();
}
[HttpPost]
public ActionResult Remove(string[] files) // the default field name. See RemoveField
{
if (files != null)
{
try
{
foreach (var fullName in files)
{
var fileName = Path.GetFileName(fullName);
var physicalPath = Path.Combine(HostingEnvironment.WebRootPath, fileName);
if (System.IO.File.Exists(physicalPath))
{
// Implement security mechanisms here - prevent path traversals,
// check for allowed extensions, types, permissions, etc.
// this sample always deletes the file from the root and is not sufficient for a real application
System.IO.File.Delete(physicalPath);
}
}
}
catch
{
// implement error handling here, this merely indicates a failure to the upload
Response.StatusCode = 500;
Response.WriteAsync("some error message"); // custom error message
}
}
// Return an empty string message in this case
return new EmptyResult();
}
}
}
<TelerikGrid Data="@CustomerViewModel.Customers" EditMode="@GridEditMode.Inline" Height="800px" Pageable="true" Sortable="true" SortMode="@SortMode.Single" OnUpdate="@(async args => await CustomerViewModel.UpdateCustomerAsync(args))" OnDelete="@(async args => await CustomerViewModel.DeleteCustomerAsync(args))" OnCreate="@(async args => await CustomerViewModel.CreateCustomerAsync(args))"> <GridToolBar> <GridCommandButton Command="Add" Icon="Add">Add Customer</GridCommandButton> <GridSearchBox DebounceDelay="200"></GridSearchBox> </GridToolBar> <GridColumns> <GridColumn Field="@nameof(Customer.Name)" Title="Customer" /> <GridColumn Editable="false" Field="@nameof(Customer.Jurisdictions)" Title="Jur. Count" /> <GridColumn Editable="false" Field="@nameof(Customer.JurisdictionsWithPersonalForms)" Title="Jur. w/Personal forms" /> <GridColumn Editable="false" Field="@nameof(Customer.JurisdictionsWithCorporateForms)" Title="Jur. w/Corporate forms" /> <GridColumn Editable="false" Field="@nameof(Customer.JurisdictionsWithForms)" Title="Jur. with forms (total)" /> <GridColumn Editable="false" Field="@nameof(Customer.JurisdictionsWithLicense)" Title="Jur. License Count" /> <GridCommandColumn> <GridCommandButton Command="Edit" Icon="edit"></GridCommandButton> <GridCommandButton Command="Delete" Icon="delete"></GridCommandButton> <GridCommandButton Command="Save" Icon="save" ShowInEdit="true"></GridCommandButton> <GridCommandButton Command="Cancel" Icon="cancel" ShowInEdit="true"></GridCommandButton> @*<GridCommandButton Title="Jurisdictions" OnClick="JurisdictionsShow">Jurisdictions</GridCommandButton>*@ </GridCommandColumn> </GridColumns> <DetailTemplate> @{ Customer customer = context as Customer; <CustomerJurisdictionsGrid CustomerId="@customer.Id" OnDeleteCallback="@OnDeleteCustomerCallback"/> } </DetailTemplate></TelerikGrid>
nested
<TelerikGrid Data="@ViewModel.CustomerJurisdictions" Pageable="true" Sortable="true" PageSize="20" SortMode="@SortMode.Single" Height="800px" OnDelete="@(async args=> await ViewModel.DeleteCustomerJurisdictionAsync(args))"> <GridColumns> <GridColumn Field="@nameof(CustomerJurisdiction.JurisName)" Title="Name"></GridColumn> <GridColumn Field="@nameof(CustomerJurisdiction.PersFormsCount)" Title="Personal Forms"></GridColumn> <GridColumn Field="@nameof(CustomerJurisdiction.CorpFormsCount)" Title="Corporate Forms"></GridColumn> <GridColumn Field="@nameof(CustomerJurisdiction.JurisTypeDescription)" Title="Type"></GridColumn> <GridColumn Field="@nameof(CustomerJurisdiction.JurisStateDescription)" Title="State"></GridColumn> <GridColumn Field="@nameof(CustomerJurisdiction.JurisCountryDescription)" Title="Country"></GridColumn> <GridColumn Field="@nameof(CustomerJurisdiction.LastUpdated)" Title="Last Updated"></GridColumn> <GridCommandColumn> <GridCommandButton Command="Delete" Icon="delete"></GridCommandButton> </GridCommandColumn> </GridColumns></TelerikGrid>@code { [Parameter] public int CustomerId { get; set; } [Parameter] public EventCallback<CustomerEventArgs> OnDeleteCallback { get; set; } protected override async Task OnParametersSetAsync() { Console.WriteLine(ViewModel); await ViewModel.LoadCustomerJurisdictionsAsync(CustomerId); }}
so basically if thу parameter to the nested grid is not primitive, OnParametersSetAsync will be fired twice, would appreciate for the work around
The Datepicker is using Sunday as the first day of week, my Windows 10 machine is set up to use UK dates/times and Monday is selected as first day of week.
I am using Client (webasm) version of Blazor.
Do I need to change the culture in the code?
I inserted a Loader component to my project:
<TelerikButton ButtonType="@ButtonType.Button" OnClick="@CancelForm">Cancel</TelerikButton>
<TelerikButton ButtonType="@ButtonType.Submit" Primary="true" Enabled="@Activado">
<TelerikLoader Visible="@IsGeneratingReport" ThemeColor="light"></TelerikLoader>
@( Activado ? "Creando recogida" : "Recogida creada" )
</TelerikButton>
But it makes me mistake:
"Found Markup element with unexpected name 'TelerikLoader'. If this is intended to be a component , add @using directive for its namespace".
Download the TelerikBlazorAppLibManSample project and it has the same error. In the project I have referenced Telerik for Blazor and I use other components: TelerikTabStrip, TelerikTextBox, etc. and i don't have this problem.
Thank you.
Juan