Aggregate Exception Asp.Net Core 5.0 - asp.net-core

I have an Mvc project which is based on Asp.Net Core 5.0 . I have my own Core Layer and i have my own Photo,Video uploader method which is based my FileRepo class.
Here is my FileModel class:
public class FileModel
{
public int FileID { get; set; }
public string FileName { get; set; }
public string FileType { get; set; }
public string FileExtension { get; set; }
public string FileSlug { get; set; }
public string FilePath { get; set; }
public byte[] Data { get; set; }
}
Here is my File Uploader method :
public interface IFileUploader
{
Task<FileModel> FileUploadToDatabase(List<IFormFile> files);
Task<FileModel> FileUploadToPath(List<IFormFile> files);
Task<bool> FileDeleteFromPath(int id);
}
public class FileUploader : IFileUploader
{
private FileModel _fileModel;
public FileUploader(FileModel fileModel)
{
_fileModel = fileModel;
}
public async Task<FileModel> FileUploadToDatabase(List<IFormFile> files)
{
foreach (var file in files)
{
var fileName = Path.GetFileNameWithoutExtension(file.FileName);
var extension = Path.GetExtension(file.FileName);
_fileModel = new FileModel
{
FileName = fileName,
FileType = file.ContentType
};
using (var dataStream = new MemoryStream())
{
await file.CopyToAsync(dataStream);
_fileModel.Data = dataStream.ToArray();
}
}
return _fileModel;
}
public async Task<FileModel> FileUploadToPath(List<IFormFile> files)
{
foreach (var file in files)
{
var basePath = Path.Combine(Directory.GetCurrentDirectory() + "\\Files\\");
bool basePathExists = Directory.Exists(basePath);
if (!basePathExists) Directory.CreateDirectory(basePath);
var fileName = Path.GetFileNameWithoutExtension(file.FileName);
var filePath = Path.Combine(basePath, file.FileName);
var extension = Path.GetExtension(file.FileName);
if (!File.Exists(filePath))
{
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
_fileModel = new FileModel
{
FileName = fileName,
FileType = file.ContentType,
FilePath = filePath
};
}
}
return _fileModel;
}
}
As u guys can see,its a different layer and there is nothing related with my Mvc project.
Im getting error when i add those extension to my Mvc project.
The error says me that :
'Some services are not able to be constructed (Error while validating the service descriptor
'ServiceType: CORE_HBKSOFTWARE.Interfaces.IFileUploader Lifetime: Singleton ImplementationType:
CORE_HBKSOFTWARE.Classes.FileUploader': Unable to resolve service for type
'CORE_HBKSOFTWARE.Models.FileModel' while attempting to activate
'CORE_HBKSOFTWARE.Classes.FileUploader'.)'
I dont know why im getting that error. That FileModel class is seems to okey to me and i still dont know. I allready add my services.AddSingleton<IFileUploader, FileUploader>(); to my Startup.cs .
Thanks for any suggestion !

If you want to use constructor injection to create an instance of FileModel in your FileUploader class you need to register it to the IoC Container. You do that by calling following method in the ConfigureServices method:
services.AddSingleton<FileModel>();
You can also choose a different lifetime by calling AddScoped or AddTransient.

Related

Blazor: How to pass multiple parameter's from NavigateTo to a WEB API controller to download a file

I'm trying to use NavivgateTo in Blazor to pass a file id and name to download a file from my Download controller.
What is the proper setup? I've tried a number of possibilities and I keep seeing an error: Sorry, there is nothing at this address.
Razor Page
public async Task SelectedDisplayDbItemChanged(DisplayDbItemsComboBoxItemDTO item)
{
Data = null;
Data = GetDataTable();
var fileId = await utilities.ExportDataTableToFile((DataTable)Data).ConfigureAwait(false);
//navigationManager.NavigateTo($"api/download/fileId/" + fileId + "/fileName/" + "myfile", true);
//?data1=678&data2=c-sharpcorner
navigationManager.NavigateTo($"api/Download/{fileId}/{"myfile"}", true);
}
Controller:
[HttpPost("Download/{fileId}/{fileName}")]
public async Task<IActionResult> Download(string fileId, string fileName)
{
using (var ms = new MemoryStream())
{
var fullPath = Path.Combine(DownloadPath, fileId);
await using (var stream = new FileStream(fullPath, FileMode.Open))
{
await stream.CopyToAsync(ms);
}
ms.Position = 0;
return File(ms, "application/octet-stream", $"{fileName}.xlsx");
}
}
I've seen a lot of examples from the Razor page to the Razor page, but not from NavigateTo to a controller with passing multiple parameters.
I've tried these responses as well: https://stackoverflow.com/a/71130256/9594249
https://stackoverflow.com/a/71130256/9594249
Not like Asp.net MVC or razor page, in Blazor parameters are passed by [Parameter] tag
#page "/Download/{fileId}/{fileName}"
#code {
[Parameter]
public string? fileId { get; set; }
[Parameter]
public string? fileName { get; set; }
}
please refer : https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-6.0
(Updated)
add to Program.cs or Startup.cs:
builder.Services.AddRazorPages(options => {
options.Conventions.AddPageRoute("/DownloadPage", "Download/{fileId?}/{fileName?}");
}
});
Pages/DownloadPage.cshtml
#page "{fileId?}/{fileName?}"
#model BlazorApp.Pages.DownloadModel
Pages/DownloadPage.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace BlazorApp.Pages;
public class DownloadModel : PageModel
{
private readonly IWebHostEnvironment _env;
public DownloadModel(IWebHostEnvironment env)
{
_env = env;
}
public IActionResult OnGet()
{
// work with RouteData.Values["fileId"] and RouteData.Values["fileName"]
}
}
please refer :
https://learn.microsoft.com/en-us/answers/questions/243420/blazor-server-app-downlaod-files-from-server.html
https://learn.microsoft.com/ko-kr/aspnet/core/razor-pages/razor-pages-conventions?view=aspnetcore-6.0

How to send object which contains IEnumerable via Refit on NetCore?

I have to send a request object via Refit which contains 2 IEnumerable and one string, but for some reason I can't send the object forward.
I've tried to use all the paramets from the interface. Ex: [Query(CollectionFormat.Csv)] or Multi / Pipes but no success.
I've also tried to create my own CustomUrlParameterFormatter but unfortunately here I'm stuck, because I don't see a good way to retrieve the name of the property from the object request that I'm sending.
The code for CustomUrlParameterFormatter
public class CustomUrlParameterFormatter : IUrlParameterFormatter
{
public string Format(object value, ParameterInfo parameterInfo)
{
if(value is IEnumerable enumerable)
{
var result = ToQueryString(enumerable, parameterInfo.Name);
return result;
}
return string.Empty;
}
public static string ToQueryString(IEnumerable query, string parameterName)
{
var values = query.Cast<object>().Select(ToString).ToArray();
var separator = parameterName + "=";
return values.Any() ? separator + string.Join("&" + separator, values) : "";
}
public static string ToString(object value)
{
var json = JsonConvert.SerializeObject(value).Replace("\\\"", "\"").Trim('"');
return Uri.EscapeUriString(json);
}
}
The Call from the IService that I'm using
[Get("/TestMethod")]
Task<HttpResponseMessage> TestMethod([Query]TestRequestDTO requestDTO, [Header("X-Correlation-ID")] string correlationId);
The Request object
public class TestRequestDTO
{
public IEnumerable<long> EnumOne { get; set; }
public IEnumerable<long> EnumTwo { get; set; }
public string MethodString { get; set; }
}
Also the RefitClient configuration
var refitSettings = new RefitSettings();
refitSettings.UrlParameterFormatter = new CustomUrlParameterFormatter();
services.AddRefitClient<IService>(refitSettings)
.ConfigureHttpClient(c => c.BaseAddress = new Uri(settings.Services.IService));
What I'm trying to achieve is something like
TestMethod?EnumOne =123&EnumOne =321&EnumTwo=123&EnumTwo=321&methodString=asdsaa
and instead I'm receiving other behavior
without CustomUrlParameterFormatter()
TestMethod?EnumOne=System.Collections.Generic.List`1%5BSystem.Int64%5D&EnumTwo=System.Collections.Generic.List`1%5BSystem.Int64%5D&MethodString=sdf

Protobuf.Net: Serializing List<Uri> throws "Unable to cast object of type 'System.Uri' to type 'System.String'"

The title says it all, Protobuf.net correctly serializes Uri, but won't serialize List<Uri>
[ProtoContract]
class SingleUri
{
[ProtoMember(1)]
public Uri Uri { get; set; }
}
[ProtoContract]
class MultiUri
{
[ProtoMember(1)]
public List<Uri> Uris { get; set; }
}
static void Main(string[] args)
{
var single = new SingleUri { Uri = new Uri("http://www.google.com") };
using (var file = File.Create("single.bin"))
// Works a treat
Serializer.Serialize(file, single);
var multi = new MultiUri { Uris = new List<Uri> { single.Uri } };
using (var file = File.Create("multi.bin"))
// fails with System.InvalidCastException: Unable to cast object
//of type 'System.Uri' to type 'System.String'.
Serializer.Serialize(file, multi);
}
I'm running this against the latest NuGet package as of time of writing.
Can anyone tell me what I'm missing here? Any workaround for this?
Thanks.

webapi receiving null parameter

I'm attempting to POST an object to a WebAPI controller that accepts a complex type as the parameter but the parameter recived is null. Any ideas why? The request is hitting the WebAPI method properly and the parameter is null.
Model :
namespace DMAX.BLL.MASReports.Models
{
public class StatsCriteria
{
#region Constructors and Methods
public StatsCriteria()
{
}
#endregion
#region Properties and Fields
private string _masnum;
private string _notchosen;
private int _currentPage = 1;
private bool _isPrint = false;
private bool _isEmail = false;
private bool _isAjax = false;
public string Masnums { get {
if (!string.IsNullOrEmpty(_masnum)) {
_masnum = _masnum.Replace("'", "");
if (!string.IsNullOrEmpty(NotChosen)) {
string[] notchosenlist = NotChosen.Split(',');
foreach (var notchosen in notchosenlist) {
_masnum = this.RemoveNotChosen(_masnum, notchosen);
}
}
return _masnum;
}
return null;
}
set { _masnum = value; }
}
public string AgentId { get; set; }
public string LicenseNum { get; set; }
public string AgentFullName { get; set; }
public string HeaderName { get; set; }
#endregion
}
}
}
Here's the code at client : [ The StatsCriteria is part of the project BLL and I am referencing it in MASReports project]
namespace MASReports.Controllers
{
public ActionResult Reports(StatsCriteria criteria)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.PostAsJsonAsync("http://localhost:52765/api/reports", criteria.Masnums.ToString()).Result;
return View("CMAReport", response);
}
}
Here's the signature for my controller in Webapi.
[ The StatsCriteria is part of the project BLL and I have a reference to that project in ReportsAPI project]
[ The CMAReportVM, CMAReport are part of the project BLL and I have a reference to BLL project in ReportsAPIproject]
namespace ReportsAPI.Controllers
{
public class ReportsController : ApiController
{
[HttpPost]
public CMAReportVM Reports([FromBody] StatsCriteria criteria)
{
var cmaReport = Service3.GetCMAReport(criteria.Masnums);
//Create Map to enable mapping business object to View Model
Mapper.CreateMap<CMAReport, CMAReportVM>();
// Maps model to VM model class
var cmaVM = Mapper.Map<CMAReport, CMAReportVM>(cmaReport);
reutn cmaVM;
}
}
}
// and here's my routing:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
and here's my Golbal.asax of Web api
namespace ReportsAPI
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("json", "true", "application/json"));
}
}
}
You are posting a string:
var response = client.PostAsJsonAsync("http://localhost:52765/api/reports", criteria.Masnums.ToString()).Result;
Your controller method expect a StatsCriteria object. Either change the signature of your controller method to accept a string or change the post call.
Assuming that the controller method signature is correct the post should be something like this:
var response = client.PostAsJsonAsync("http://localhost:52765/api/reports", criteria).Result;
If this doesn't help I recommend to use fiddler to check what the message looks like when you post it.

MVC Web Api returning serialized response instead of css

I am having an issue returning css from a web api controller. The code takes a request for a css file and returns it after reading it from the database.
The problem is that the web api code seems to be serializing the response and returning that instead of the css itself.
Here you can see a link tag that the browser is sending to the server which should return css. You can also see that the response looks like a serialization of my css instead of just the css string.
My request and response headers:
My controller looks like this:
public HttpResponseMessage Get(string fileName, string siteId, int id)
{
var fileData = ReadSomeCssFromTheDatabase();
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new ByteArrayContent(fileData);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/css");
result.Headers.CacheControl = new CacheControlHeaderValue();
result.Headers.CacheControl.MaxAge = TimeSpan.FromHours(0);
result.Headers.CacheControl.MustRevalidate = true;
return result;
}
There is a “text/css” formatter installed that is being created but not being hit for some reason.
public class CssFormatter : MediaTypeFormatter
{
public CssFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/css"));
}
public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
{
var taskCompletionSource = new TaskCompletionSource<object>();
try
{
var memoryStream = new MemoryStream();
readStream.CopyTo(memoryStream);
var s = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
taskCompletionSource.SetResult(s);
}
catch (Exception e)
{
taskCompletionSource.SetException(e);
}
return taskCompletionSource.Task;
}
public override bool CanReadType(Type type)
{
return type == typeof(string);
}
public override bool CanWriteType(Type type)
{
return false;
}
}
What am I doing wrong?
Your formatter would not be hit because you are not going through content negotiation process (as you are returning HttpResponseMessage in your action...you could use Request.CreateResponse<> to make conneg process run)
You are trying to 'write' the css content right?...but i see that CanWriteType is returning 'false' and also you seem to be overriding ReadFromStreamAsync instead of WriteToStreamAsync?
An example of how you could do(from what i understood about the above scenario):
public class DownloadFileInfo
{
public string FileName { get; set; }
public string SiteId { get; set; }
public int Id { get; set; }
}
public HttpResponseMessage Get([FromUri]DownloadFileInfo info)
{
// validate the input
//Request.CreateResponse<> would run content negotiation and get the appropriate formatter
//if you are asking for text/css in Accept header OR if your uri ends with .css extension, you should see your css formatter getting picked up.
HttpResponseMessage response = Request.CreateResponse<DownloadFileInfo>(HttpStatusCode.OK, info);
response.Headers.CacheControl = new CacheControlHeaderValue();
response.Headers.CacheControl.MaxAge = TimeSpan.FromHours(0);
response.Headers.CacheControl.MustRevalidate = true;
return response;
}
public class CssFormatter : MediaTypeFormatter
{
public CssFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/css"));
}
public override bool CanReadType(Type type)
{
return false;
}
public override bool CanWriteType(Type type)
{
return type == typeof(DownloadFileInfo);
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
//use the 'value' having DownloadFileInfo object to get the details from the database.
// Fead from database and if you can get it as a Stream, then you just need to copy it to the 'writeStream'
}
}