- Details
- Written by: Stanko Milosev
- Category: C#
- Hits: 4096
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.
- Details
- Written by: Stanko Milosev
- Category: C#
- Hits: 599
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.
- Details
- Written by: Stanko Milosev
- Category: C#
- Hits: 693
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
- Details
- Written by: Stanko Milosev
- Category: C#
- Hits: 1130
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.