venerdì 17 novembre 2017

XE One Day - Performance & Optimization


XE.NET ha organizzato per sabato 18 novembre un’intera giornata dedicata a tecniche e tecnologie per spingere le performance delle nostre applicazioni over the top!

Per info ed iscrizioni: http://www.xedotnet.org/eventi/

martedì 18 aprile 2017

Angular Day 2017

L'evento italiano su Angular

Si parlerà di nuove metodologie di sviluppo, best practice, casi di successo, qualità del codice, modularizzazione, form, direttive custom, typescript.

Per maggiori info http://2017.angularday.it/

venerdì 10 febbraio 2017

Web API - POST Content and Data with a MultipartFormDataStreamProvider

C# .NET Framework 4.0, Web API, Newtonsoft.Json.dll

I want to send content file and data to a Web API service, in this case a pdf document and some metadata about it.
In first time, I have developed a custom MultipartFormDataStreamProvider

// We implement MultipartFormDataStreamProvider to override the filename of File which
// will be stored on server, or else the default name will be of the format like Body-
// Part_{GUID}. In the following implementation we simply get the FileName from
// ContentDisposition Header of the Request Body.
public class CustomMultipartFormDataStreamProvider : MultipartFormDataStreamProvider
{
    public CustomMultipartFormDataStreamProvider(string path) : base(path)
    {}

    public override string GetLocalFileName(HttpContentHeaders headers)
   {
        return headers.ContentDisposition.FileName.Replace("\"", string.Empty);
   }             

   /// <summary>
   /// Gets the attachment.
   /// </summary>
   /// <returns></returns>
   public AttachmentModel GetAttachment()
   {
       try
       {
                // This is a custom object.
                AttachmentModel attachment = null;

                var key = FormData.AllKeys[0];

                var strings = FormData.GetValues(key);
                if (strings != null)
                {
                    attachment = JsonConvert.DeserializeObject<AttachmentModel>(strings[0]);
                }

                return attachment;
        }
        catch (Exception ex)
        {
            return null;
         }
    }

Then I ‘ve developed this ApiController:

public class AttachmentController : ApiController
{
[HttpPost]
[Authorize]
public async Task<HttpResponseMessage> Post()
{
    string imageFile = null;
    FileStream fileStream = null;
    try
    {
        #region Check validity

        // Check whether the POST operation is MultiPart?
        if (!Request.Content.IsMimeMultipartContent())
        {                                                                            
            return Request.CreateResponse(HttpStatusCode.OK, "File format not valid.");
        }

        // This is a folder where we save the attachment temporarily.
        string documentUploadPath = System.Configuration.ConfigurationManager.AppSettings["DocumentUploadPath"];
        string root = string.Concat(HostingEnvironment.MapPath("~/"), documentUploadPath);

        CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(root);
        
        // Read all contents of multipart message into CustomMultipartFormDataStreamProvider.
        await Request.Content.ReadAsMultipartAsync(provider);

        imageFile = provider.FileData[0].LocalFileName;

        if (string.IsNullOrEmpty(imageFile))
        {                                                                            
            return Request.CreateResponse(HttpStatusCode.OK, "File not found.");
        }

        try
        {
            fileStream = new FileStream(imageFile, FileMode.Open);
        }
        catch
        {                                                                            
            return Request.CreateResponse(HttpStatusCode.OK, "Attachment not recognized.");
        }
       
        // This is a custom object.
         AttachmentModel Attachment = provider.GetAttachment();

        if (Attachment == null)
        {                                                                            
            return Request.CreateResponse(HttpStatusCode.OK, "Attachment not recognized.");
        }

        MemoryStream memoryStream = new MemoryStream();
        fileStream.CopyTo(memoryStream);
        Attachment.Content = memoryStream.ToArray();

        #endregion

        // Other internal consideration and operations.
        // ...
        
        var response = Request.CreateResponse(HttpStatusCode.OK, “OK”;

        return response;
    }
    catch (Exception ex)
    {                                                             
        HttpError httpError = new HttpError {Message = "Internal error."};
        return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, httpError);
    }
    finally
    {
        if (imageFile != null && File.Exists(imageFile))
        {
            if (fileStream != null)
            {
                fileStream.Close();
                fileStream.Dispose();
            }
            File.Delete(imageFile);
        }
    }
 }
  
Ok. For testing I have used fiddler with a script like this:


Content-Type: multipart/form-data; boundary=-------------------------acebdf13572468
Host: localhost
Connection: keep-alive
Cache-Control: max-age=0
Accept: application/json, text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: it-IT,en;q=0.8
Content-Length: 225317

Request body:

---------------------------acebdf13572468
Content-Disposition: form-data; name="fieldNameHere"; filename="test.pdf"
Content-Type: application/pdf

<@INCLUDE *C:\temp\test.pdf*@>
---------------------------acebdf13572468
Content-Disposition: form-data; name="attachment"

{
  "IdProtocol": "1",
  "application": "TEST",
  "filename": "test.pdf"
}
---------------------------acebdf13572468--

It is very important to close the request with these two minus signs!



Finally a C# function for calling this web service:

private bool SendAttachment(AttachmentModel attachment)
{
     // This is a custom object.
     // AttachmentModel attachment

     HttpClient client = new HttpClient();
                                              
     using (var content = new MultipartFormDataContent())
     {
         var values = new[]
         {
             new KeyValuePair<string, string>("attachment", JsonConvert.SerializeObject(attachment))
         };

         foreach (var keyValuePair in values)
         {
             content.Add(new StringContent(keyValuePair.Value), keyValuePair.Key);
         }

         var fileContent = new ByteArrayContent(attachment.Content);
         fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
         {
             FileName = attachment.NomeFile
         };
         content.Add(fileContent);

         var requestUri = "http://localhost/AttachmentManagerService/api/attachment";
         var result = client.PostAsync(requestUri, content);
         result.Wait();

         if (result.Result.IsSuccessStatusCode)
         {
             // check json format
             string responseContent = result.Result.Content.ReadAsStringAsync().Result;

             // if parse not throw exceptions, deserialize string...
                                                                             
             return true;
         }
         else
         {
             return false;
         }
     }
 }

I hope it is clear, otherwise if you want to also send me an email.


Kind regards!