Micro blog about Answer to the Ultimate Question of Life, the Universe, and Everything.
  • Home
    • List all categories
    • Sitemap
  • Downloads
    • WebSphere
    • Hitachi902
    • Hospital
    • Kryptonite
    • OCR
    • APK
  • About me
    • Gallery
      • Italy2022
      • Côte d'Azur 2024
    • Curriculum vitae
      • Resume
      • Lebenslauf
    • Social networks
      • Facebook
      • Twitter
      • LinkedIn
      • Xing
      • GitHub
      • Google Maps
      • Sports tracker
    • Adventures planning
  1. You are here:  
  2. Home

Post image and additional data to WebAPI

Details
Written by: Stanko Milosev
Category: C#
Published: 14 March 2024
Last Updated: 14 March 2024
Hits: 5002

According to https://stackoverflow.com/a/14413414

Natively WebAPI doesn't support binding of multiple POST parameters. 

Here I already gave two examples of WebAPI with multiple Post parameters. Now I will use similiar approach to send image plus additional data, like file and folder name.

First don't forget in Program.cs to add Service:

builder.Services.AddMvc().AddNewtonsoftJson();

Controller:

using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;

namespace UploadImageServer.Controllers;

public class UploadImageController : Controller
{
    [HttpPost]
    [Route("UploadImage")]

    public async Task<IActionResult> UploadImage([FromBody] JObject? data)
    {
        if (data is null) return BadRequest(new { message = "No image." });
        string? base64Image = data["image"]?.ToString();

        if (base64Image == null) return BadRequest(new { message = "No image." });
        byte[] imageBytes = Convert.FromBase64String(base64Image);

        Directory.CreateDirectory(data["folderName"]?.ToString() ?? string.Empty);

        string imagePath = $"{data["folderName"]}\\{data["fileName"]}";
        await System.IO.File.WriteAllBytesAsync(imagePath, imageBytes);

        return Ok(new { message = "Image uploaded successfully." });
    }
}
Server download from here.

---

Client:

using Newtonsoft.Json.Linq;
using System.Net.Http.Headers;

string imageUrl = "spring.jpg";
string base64Image = ConvertImageToBase64(imageUrl);
var jsonData = new JObject
{
    ["image"] = base64Image
    , ["fileName"] = "magnolia.jpg"
    , ["folderName"] = "spring"
};
string jsonContent = jsonData.ToString();

using HttpClient client = new HttpClient();
StringContent content = new StringContent(jsonContent);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

HttpResponseMessage response = await client.PostAsync("https://localhost:7028/UploadImage", content);

if (response.IsSuccessStatusCode)
{
    Console.WriteLine("Image uploaded successfully!");
}
else
{
    Console.WriteLine("Failed to upload image. Status code: " + response.StatusCode);
}

static string ConvertImageToBase64(string imagePath)
{
    byte[] imageBytes = File.ReadAllBytes(imagePath);
    return Convert.ToBase64String(imageBytes);
}
Client download from here.

FluentFTP async example

Details
Written by: Stanko Milosev
Category: C#
Published: 24 December 2023
Last Updated: 25 December 2023
Hits: 1227
Here is my example of async version of FluentFTP using log4net with TextBoxAppender which I already described here

For this example I have added following NuGet packages:

FluentFTP

FluentFTP.Logging

log4net

Microsoft.Extensions.Configuration.Json - this package I needed because user name and pass for FTP I have saved in JSON configuration file.

In short code looks like this:

Log4NetLogger log4NetLogger = new Log4NetLogger(log);
AsyncFtpClient client = new AsyncFtpClient(host, user, pass);
client.ValidateCertificate += OnValidateCertificate;
client.Logger = new FtpLogAdapter(log4NetLogger);
await client.AutoConnect();
await client.UploadFile(fileName, "/public_html/kmlTestDelete/test.kml");

private void OnValidateCertificate(BaseFtpClient control, FtpSslValidationEventArgs e)
{
	e.Accept = true;
}
The method OnValidateCertificate I am using to accept any certificate, this part of code I took from here

Class Log4NetLogger looks like this:

using log4net;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;

namespace FluentFTPasyncExample;

public class Log4NetLogger : ILogger
{
    private readonly ILog _log;

    public Log4NetLogger(ILog log)
    {
        _log = log;
    }

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        string message = $"{formatter(state, exception)} {exception}";
        if (!string.IsNullOrEmpty(message))
        {
            switch (logLevel)
            {
                case LogLevel.Critical:
                    _log.Fatal(message);
                    break;
                case LogLevel.Debug:
                case LogLevel.Trace:
                    _log.Debug(message);
                    break;
                case LogLevel.Error:
                    _log.Error(message);
                    break;
                case LogLevel.Information:
                    _log.Info(message);
                    break;
                case LogLevel.Warning:
                    _log.Warn(message);
                    break;
                default:
                    _log.Warn($"Encountered unknown log level {logLevel}, writing out as Info.");
                    _log.Info(message, exception);
                    break;
            }
        }
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        switch (logLevel)
        {
            case LogLevel.Critical:
                return _log.IsFatalEnabled;
            case LogLevel.Debug:
            case LogLevel.Trace:
                return _log.IsDebugEnabled;
            case LogLevel.Error:
                return _log.IsErrorEnabled;
            case LogLevel.Information:
                return _log.IsInfoEnabled;
            case LogLevel.Warning:
                return _log.IsWarnEnabled;
            default:
                throw new ArgumentOutOfRangeException(nameof(logLevel));
        }
    }

    public IDisposable BeginScope<TState>(TState state)
    {
        return null!;
    }

}
Notice that I am injecting log4net in constructor.

Example download from here.

log4net example

Details
Written by: Stanko Milosev
Category: C#
Published: 22 December 2023
Last Updated: 24 December 2023
Hits: 1036
Here is my example of log4net.

First console example

Start new console app

Install package log4net

Add XML file, name it like "log4netConfiguration.xml" and in properties set "Copy to Output Directory" to "Copy always":

<?xml version="1.0" encoding="utf-8" ?> 
<log4net>
    <appender name="myConsoleAppender" type="log4net.Appender.ConsoleAppender">
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline" />
        </layout>
    </appender>
    
    <root>
        <level value="DEBUG" />
        <appender-ref ref="myConsoleAppender" />
    </root>
</log4net>

Here notice the name of appender: myConsoleAppender

Code:

using log4net;
using log4net.Repository;
using System.Reflection;

if (!File.Exists("log4netConfiguration.xml"))
    throw new Exception("File log4netConfiguration.xml does not exist");

ILoggerRepository loggerRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
log4net.Config.XmlConfigurator.Configure(loggerRepository, new FileInfo("log4netConfiguration.xml"));
var log = LogManager.GetLogger(MethodBase.GetCurrentMethod()?.DeclaringType);
log.Debug("test");
Example download from here

Second console and file example

Just change XML to:

<?xml version="1.0" encoding="utf-8" ?> 
<log4net>
    <appender name="myConsoleAppender" type="log4net.Appender.ConsoleAppender">
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline" />
        </layout>
    </appender>
	
	<appender name="myRollingFileAppender" type="log4net.Appender.RollingFileAppender">
		<file value="example.log" />
		<appendToFile value="true" />
		<maximumFileSize value="100KB" />
		<maxSizeRollBackups value="2" />
 
		<layout type="log4net.Layout.PatternLayout">
			<conversionPattern value="%level %thread %logger - %message%newline" />
		</layout>
	</appender>	
    
    <root>
        <level value="DEBUG" />
        <appender-ref ref="myConsoleAppender" />
        <appender-ref ref="myRollingFileAppender" />
    </root>
</log4net>
Notice myRollingFileAppender.

Third WinForms and TextBox example

This example I took from here

XML configuration:

<?xml version="1.0" encoding="utf-8" ?>
<log4net>

	<appender name="myTextBoxAppender" type="log4netWinFormsExample.TextBoxAppender, log4netWinFormsExample">
		<formName value="Form1"/>
		<textBoxName value="textBox1"/>
		<layout type="log4net.Layout.PatternLayout">
			<conversionPattern value="%date %-5level %logger - %message" />
		</layout>
	</appender>

	<root>
		<level value="DEBUG" />
		<appender-ref ref="myTextBoxAppender" />
	</root>
</log4net>
Here notice that I have added namespace "log4netWinFormsExample" in the type attribute of appender node:

<appender name="myTextBoxAppender" type="log4netWinFormsExample.TextBoxAppender, log4netWinFormsExample">
TextBoxAppender class:
using log4net.Appender;

namespace log4netWinFormsExample;

public class TextBoxAppender : AppenderSkeleton
{
    private TextBox _textBox;
    public TextBox AppenderTextBox
    {
        get
        {
            return _textBox;
        }
        set
        {
            _textBox = value;
        }
    }
    public string FormName { get; set; }
    public string TextBoxName { get; set; }

    private Control FindControlRecursive(Control root, string textBoxName)
    {
        if (root.Name == textBoxName) return root;
        foreach (Control c in root.Controls)
        {
            Control t = FindControlRecursive(c, textBoxName);
            if (t != null) return t;
        }
        return null;
    }

    protected override void Append(log4net.Core.LoggingEvent loggingEvent)
    {
        if (_textBox == null)
        {
            if (String.IsNullOrEmpty(FormName) ||
                String.IsNullOrEmpty(TextBoxName))
                return;

            Form form = Application.OpenForms[FormName];
            if (form == null)
                return;

            _textBox = (TextBox)FindControlRecursive(form, TextBoxName);
            if (_textBox == null)
                return;

            form.FormClosing += (s, e) => _textBox = null;
        }
        _textBox.Invoke((MethodInvoker)delegate
        {
            _textBox.AppendText(loggingEvent.RenderedMessage + Environment.NewLine);
        });
    }
}
Here notice line:
_textBox.AppendText(loggingEvent.RenderedMessage + Environment.NewLine);
Instead you could write:
_textBox.AppendText(RenderLoggingEvent(loggingEvent));
To take advantage of a pattern layout as described in this comment.

The main code:

using System.Reflection;
using log4net;
using log4net.Repository;

namespace log4netWinFormsExample;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void btnLogIt_Click(object sender, EventArgs e)
    {
        if (!File.Exists("log4netConfiguration.xml"))
            throw new Exception("File log4netConfiguration.xml does not exist");

        ILoggerRepository loggerRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
        log4net.Config.XmlConfigurator.Configure(loggerRepository, new FileInfo("log4netConfiguration.xml"));
        var log = LogManager.GetLogger(MethodBase.GetCurrentMethod()?.DeclaringType);
        log.Debug("test");
    }
}
Example download from here

Two examples of WebAPI with multiple Post parameters

Details
Written by: Stanko Milosev
Category: C#
Published: 15 July 2023
Last Updated: 15 July 2023
Hits: 1688
First example
WebAPI:
[HttpPost]
public string Post(string value1, string value2)
{
	return $"Sent: {value1}, {value2}";
}
Console:
Console.WriteLine("************* POST *************");

HttpClient httpClientPost = new HttpClient();
Task<HttpResponseMessage> httpResponseMessage = httpClientPost.PostAsync(@"https://localhost:7037/api/Values?value1=test1&value2=test2'", null);
Task<string> httpClientPostResult = httpResponseMessage.Result.Content.ReadAsStringAsync();
Console.WriteLine(httpClientPostResult.Result);
Example download from here

---

Second example.

First install Microsoft.AspNetCore.Mvc.NewtonsoftJson

In \WebApi\WebApi\Program.cs add line:

builder.Services.AddMvc().AddNewtonsoftJson();
Now Program.cs looks like:
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddMvc().AddNewtonsoftJson();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();
Controller:
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json.Linq;

namespace WebApi.Controllers;

[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
    // POST api/<ValuesController>
    [HttpPost]
    public string Post([FromBody] JObject data)
    {
        return "test";
    }
}
Console:
using System.Text;

Console.WriteLine("************* POST *************");

HttpClient httpClientPost = new HttpClient();

Task<HttpResponseMessage> httpResponseMessage = httpClientPost.PostAsync(@"https://localhost:7037/api/Values"
    , new StringContent(@"{""additionalProp1"":[""string""],""additionalProp2"":[""string""],""additionalProp3"":[""string""]}"
        , Encoding.UTF8
        , "application/json"));

Task<string> httpClientPostResult = httpResponseMessage.Result.Content.ReadAsStringAsync();
Console.WriteLine(httpClientPostResult.Result);
Taken from here.

Example download from here.

  1. HttpClient Get and Post
  2. Automatically restore NuGet packages
  3. Two ways of getting window handle and title
  4. Example of KML file with images

Subcategories

C#

Azure

ASP.NET

JavaScript

Software Development Philosophy

MS SQL

IBM WebSphere MQ

MySQL

Joomla

Delphi

PHP

Windows

Life

Lazarus

Downloads

Android

CSS

Chrome

HTML

Linux

Eclipse

Page 5 of 163

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10