Reading static files in ASP.NET Blazor - asp.net-core

I have a client side Blazor Application. I want to have an appsetting.json file for my client-side configuration like we have an environment.ts in
Angular.
For that, I am keeping a ConfigFiles folder under wwwroot and a JSON file inside of it. I am trying to read this file as below.
First get the path:
public static class ConfigFiles
{
public static string GetPath(string fileName)
{
return Path.Combine("ConfigFiles", fileName);
}
}
Than read it:
public string GetBaseUrl()
{
string T = string.Empty;
try
{
T = File.ReadAllText(ConfigFiles.GetPath("appsettings.json"));
}
catch (Exception ex)
{
T = ex.Message;
}
return T;
}
But I always get the error:
Could not find a part of the path "/ConfigFiles/appsettings.json".
Inside the GetPath() method, I also tried:
return Path.Combine("wwwroot/ConfigFiles", fileName);
But I still get the same error:
Could not find a part of the path "wwwroot/ConfigFiles/appsettings.json".
Since there is no concept of IHostingEnvironmentin client-side Blazor, what is the correct way to read a static JSON file here?

I have a client side Blazor Application
OK, That means that File.ReadAllText(...) and Path.Combine(...) are not going to work at all.
Client-side means that you could be running on Android or Mac-OS or whatever.
The Blazor team provides you with a complete sample of how to read a file, in the form of the FetchData sample page.
forecasts = await Http.GetJsonAsync<WeatherForecast[]>("sample-data/weather.json");
this gets you the contents of a file in wwwroot/sample-data
You can use Http.GetStringAsync(...) if you want AllText
If you want to have per-user settings then look into the Blazored.LocalStorage package.

Related

How to access a file server share from an ASP.NET Core web API application published in IIS within the same domain?

I need access to files that are in a files server in my LAN from my Angular app.
I assume that I need to publish my Angular app in the same network, that is, in my IIS Server inside the same LAN
Now on my local machine, I try to access my shared folder \192.168.100.7\OfertasHistoric" but I donĀ“t know how to do it.
When I try this
[HttpGet("directorio")]
public async Task<ActionResult<string[]>> GetDirectoryContents()
{
string[] files = Directory.GetFiles(#"\\192.168.100.7\ofertashistorico");
return files;
}
I get this error
System.IO.DirectoryNotFoundException: Could not find a part of the path '/Users/kintela/Repos/Intranet-WebAPI/Intranet.API/\192.168.100.7\ofertashistorico'
It seems that the path that you give to the GetFiles method only searches from the current directory where the project is located downwards and I don't know how to indicate a different one.
I also do not know how to manage the issue of the credentials necessary to access said resource
Any idea, please?
Thanks
I am using below code and it works for me. Please check it.
Steps:
Navigate to the path like : \\192.168.2.50\ftp
Delete \ftp, the address in folder explorer should be \\192.168.2.50, find the folder you want, right click and map network drive.
You can try it with this address ftp:\\192.168.2.50, it will pop up a window. Input you usename and password, then you can check the files.
Test Result
Sample code
[HttpGet("directorio")]
public IActionResult GetDirectoryContents()
{
string networkPath = #"ftp:\\192.168.2.50";
string userName = #"Administrator";
string password = "Yy16";
#region FtpWebRequest
var networkCredential = new NetworkCredential(userName, password);
var uri = new Uri(networkPath);
var request = (FtpWebRequest)WebRequest.Create(uri);
request.Credentials = networkCredential;
request.Method = WebRequestMethods.Ftp.ListDirectory;
try
{
using (var response = (FtpWebResponse)request.GetResponse())
{
using (var stream = response.GetResponseStream())
{
using (var reader = new StreamReader(stream))
{
Console.WriteLine(reader.ReadToEnd());
}
}
}
}
catch (WebException ex)
{
Console.WriteLine("Access to the path '" + networkPath + "' is denied. Error message: " + ex.Message);
}
#endregion
return Ok();
}

File Uploading service gets failed from android whereas works with IOS

I had created the WCF service for file uploading. Its working fine when the service hits from web application or from IOS device. But its throwing an exception when it comes from Android device.
I tried to multiparse the streamdata. Its throwing an exception as like file unavailable.
public OASIS.Entity.Shared.UserFileUpload FileUpload(Stream data, string UploadMode)
{
OASIS.Entity.Shared.UserFileUpload userFileUpload = new Entity.Shared.UserFileUpload();
try
{
MultipartParser parser = new MultipartParser(data);
string fileName = string.Empty;
string filePath = string.Empty;
string allowedExtensions = string.Empty;
int allowedFileSizeMB = 0;
if (parser.FileAvailable)
{
// File Available for IOS / Web application.
// userFileUpload
}
else
{
// From android device file is getting not available.
}
}
catch (Exception exp)
{
OASIS.Utility.ExceptionManager.HandleException(exp);
userFileUpload = null;
}
return userFileUpload;
}
Expecting it should get work for android device too.
By default, WCF does not support form data files, so it looks like you are using MultipartParser to convert form data (data from a file stream uploaded through a form-data).
If this class can handle data submitted in IOS, it should also be able to handle data submitted through forms in Andriod, after all, the HTTP protocol is cross-platform.
thereby I would like to know, how do you upload data in the Andriod system?
By adding breakpoint debugging, can you use this class to parse form data properly?
I suggest you handle the form-data by creating the service with asp.net WebAPI.
https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-2
Feel free to let me know if there is anything I can help with.

ABCpdf - Download PDF with .NET Core 2.1 - HttpContext/HttpResponse

I'm creating a web page that will allow the user to download a report as a PDF using ABCpdf. But reading the documentation, the only options I see are by using doc.Save("test.pdf") (which saves the file on the server that is hosting the application) or using 'HttpContext.Current.ApplicationInstance.CompleteRequest();' (which saves on the client side, which is what I want, but HttpContext.Current is not available on .NET Core.
The band-aid solution I have is with the doc.Save(), I would save the file on the server then send a link to the view which then downloads it from the server. A potential risk I can think of is making sure to 'clean up' after the download has commenced on the server.
Is there a alternative/.NET Core equivalent for HttpContext.Current and also HttpResponse?
Here is the code that I'd like to make work:
byte[] theData = doc.GetData();
Response.ClearHeaders();
Response.ClearContent();
Response.Expires = -1000;
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", theData.Length.ToString());
Response.AddHeader("content-disposition", "attachment; filename=test.pdf");
Response.BinaryWrite(theData);
HttpContext.Current.ApplicationInstance.CompleteRequest();
Errors I get (non-verbose)
'HttpResponse' does not contain a definition for 'ClearHeaders'
'HttpResponse' does not contain a definition for 'ClearContent'
'HttpResponse' does not contain a definition for 'Expires'
'HttpResponse' does not contain a definition for 'AddHeader'
'HttpResponse' does not contain a definition for 'BinaryWrite'
'HttpContext' does not contain a definition for 'Current'
I've updated this answer to something that actually works!
GetStream does what you need, however to facilitate a file download in .NET Core it would be far easier if you create a controller as described in https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-2.1.
Then you can create a route controller to serve the file from the stream as shown in Return PDF to the Browser using Asp.net core.
So your controller would look something like:
[Route("api/[controller]")]
public class PDFController : Controller {
// GET: api/<controller>
[HttpGet]
public IActionResult Get() {
using (Doc theDoc = new Doc()) {
theDoc.FontSize = 96;
theDoc.AddText("Hello World");
Response.Headers.Clear();
Response.Headers.Add("content-disposition", "attachment; filename=test.pdf");
return new FileStreamResult(theDoc.GetStream(), "application/pdf");
}
}
}
Out of curiosity I just mocked this up and it does work - serving the PDF direct to the browser as download when you go to the URL localhost:port/api/pdf. If you make the content-disposition "inline; filename=test.pdf" it will show in the browser and be downloadable as test.pdf.
More information on the GetStream method here: https://www.websupergoo.com/helppdfnet/default.htm?page=source%2F5-abcpdf%2Fdoc%2F1-methods%2Fgetstream.htm

Tapestry: How to redirect deprecated URLs to an error page

I have legacy web application built using apache Tapestry. I have deprecated most of the application's functionality except few pages. I want this application to be running in production, but I want to redirect deprecated pages/URLs to some error page with 404 error code. Where should I configure it? I have web.xml and jboss-web.xml. Do I need to do it in some Tapestry configuration file?
You can contribute a RequestFilter to the RequestHandler service, i.e. in your AppModule:
public void contributeRequestHandler(
OrderedConfiguration<RequestFilter> configuration)
{
// Each contribution to an ordered configuration has a name,
// When necessary, you may set constraints to precisely control
// the invocation order of the contributed filter within the pipeline.
configuration.add("DeprecatedURLs", new RequestFilter() {
#Override
public boolean service(Request request,
Response response,
RequestHandler handler) throws IOException
{
String path = request.getPath();
if (isDeprecated(path))
{
response.sendError(404, "Not found");
return;
}
return handler.service(request, response);
}
}, "before:*");
}
Notice the before:* ordering constraint, it should register this filter as the first in RequestHandler's configuration.

Self updating .net CF application

I need to make my CF app self-updating through the web service.
I found one article on MSDN from 2003 that explains it quite well. However, I would like to talk practice here. Anyone really done it before or does everyone rely on third party solutions?
I have been specifically asked to do it this way, so if you know of any tips/caveats, any info is appreciated.
Thanks!
This is relatively easy to do. Basically, your application calls a web service to compare its version with the version available on the server. If the server version is newer, your application downloads the new EXE as a byte[] array.
Next, because you can't delete or overwrite a running EXE file, your application renames its original EXE file to something like "MyApplication.old" (the OS allows this, fortunately). Your app then saves the downloaded byte[] array in the same folder as the original EXE file, and with the same original name (e.g. "MyApplication.exe"). You then display a message to the user (e.g. "new version detected, please restart") and close.
When the user restarts the app, it will be the new version they're starting. The new version deletes the old file ("MyApplication.old") and the update is complete.
Having an application update itself without requiring the user to restart is a huge pain in the butt (you have to kick off a separate process to do the updating, which means a separate updater application that cannot itself be auto-updated) and I've never been able to make it work 100% reliably. I've never had a customer complain about the required restart.
I asked this same question a while back:
How to Auto-Update Windows Mobile application
Basically you need two applications.
App1: Launches the actual application, but also checks for a CAB file (installer). If the cab file is there, it executes the CAB file.
App2: Actual application. It will call a web service, passing a version number to the service and retrieve a URL back if a new version exists (). Once downloaded, you can optionally install the cab file and shut down.
One potiencial issue: if you have files that one install puts on the file system, but can't overwrite (database file, log, etc), you will need two separate installs.
To install a cab: look up wceload.exe http://msdn.microsoft.com/en-us/library/bb158700.aspx
private static bool LaunchInstaller(string cabFile)
{
// Info on WceLoad.exe
//http://msdn.microsoft.com/en-us/library/bb158700.aspx
const string installerExe = "\\windows\\wceload.exe";
const string processOptions = "";
try
{
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.FileName = installerExe;
processInfo.Arguments = processOptions + " \"" + cabFile + "\"";
var process = Process.Start(processInfo);
if (process != null)
{
process.WaitForExit();
}
return InstallationSuccessCheck(cabFile);
}
catch (Exception e)
{
MessageBox.Show("Sorry, for some reason this installation failed.\n" + e.Message);
Console.WriteLine(e);
throw;
}
}
private static bool InstallationSuccessCheck(string cabFile)
{
if (File.Exists(cabFile))
{
MessageBox.Show("Something in the install went wrong. Please contact support.");
return false;
}
return true;
}
To get the version number: Assembly.GetExecutingAssembly().GetName().Version.ToString()
To download a cab:
public void DownloadUpdatedVersion(string updateUrl)
{
var request = WebRequest.Create(updateUrl);
request.Credentials = CredentialCache.DefaultCredentials;
var response = request.GetResponse();
try
{
var dataStream = response.GetResponseStream();
string fileName = GetFileName();
var fileStream = new FileStream(fileName, FileMode.CreateNew);
ReadWriteStream(dataStream, fileStream);
}
finally
{
response.Close();
}
}
What exactly do you mean by "self-updating"? If you're referring to configuration or data, then webservices should work great. If you're talking about automatically downloading and installing a new version of itself, that's a different story.
Found this downloadable sample from Microsoft- looks like it should help.
If you want to use a third-party component, have a look at AppToDate developed by the guys at MoDaCo.