Tuesday, October 11, 2016

How to upload a file with progress indicator using WEB API

I really wanted to put a very simple example on how you can upload a file using Web API and get a progress indicator on the client. The client code here is using a console application, but I tested the code with portable libraries and it should work just fine. This is not production code! there is no security, not error handling, this is the code I used to prototype and decided to share it, it is a bare bones example.

Server code

Controller code

   public class ValuesController : ApiController
   {
        [HttpGet]
        [Route("upload/movie")]
        public string SayHello()
        {
            return "Hello World";

        }

        /// 
        /// Upload a file 
        /// 
        /// The file information
        [HttpPost]
        [Route("upload/movie")]
        [ResponseType(typeof(List))]
        public async Task SaveFileAttachment()
        {
            List model = await FileUploader.UploadAttachment(Request);
            return Request.CreateResponse(HttpStatusCode.Created, model);
        }


    }

The helper code on the server to upload a file

  public class FileUploader
  {
        const string UPLOAD_PATH = "C:\\UPLOAD";
        public static async Task> UploadAttachment(HttpRequestMessage request)
        {
            
            // Verify that this is a file upload request
            if (!request.Content.IsMimeMultipartContent())
            {
                throw new HttpResponseException(request.CreateResponse(HttpStatusCode.UnsupportedMediaType));
            }

            // Create a stream provider for setting up output streams
            var streamProvider = new MultipartFormDataStreamProvider(UPLOAD_PATH);
            MultipartFormDataStreamProvider resultProvider = null; 

            try
            {
                resultProvider = await request.Content.ReadAsMultipartAsync(streamProvider);
                
            }
            catch(Exception ex)
            {
                var x = ex.Message; // for debugging
                throw ex;
            }
          
            var files = new List();

            // Collect uploaded files
            foreach (MultipartFileData file in resultProvider.FileData)
            {
                string localFileName = Path.GetFileName(file.LocalFileName);
                string originalFileName = file.Headers.ContentDisposition.FileName;
                if (string.IsNullOrEmpty(localFileName) || string.IsNullOrEmpty(originalFileName))
                {
                    continue;
                }

                string fileName = originalFileName.Trim().Trim('"');
                files.Add(new FileUploadModel
                {
                    FileName = fileName,
                    LocalFullPath = Path.Combine(UPLOAD_PATH, localFileName),
                    Comment = String.Empty
                });
            }
            return files;
        }
    }

The client code

Console Application (notice there is a callback here to get the updated status)
 class Program
    {
        static void Main(string[] args)
        {
            string fileName = @"C:\Users\Public\Videos\Sample Videos\Wildlife.wmv";

            FileStream stream = File.Open(fileName, FileMode.Open);
            
            var response = UploadMe.UploadFile(stream, "Wild Life - uploaded.wmv", (progress) => { Console.WriteLine(progress); });
            
            Console.ReadLine();
        }

Client Helper

  public class UploadMe
    {           
        public static async Task> UploadFile(Stream fileStream, string fileName, Action callback)
        {

            ProgressMessageHandler progress = new ProgressMessageHandler();
            progress.HttpSendProgress += new EventHandler((e, args) => { callback(args.ProgressPercentage); });

            MultipartFormDataContent content = new MultipartFormDataContent();

            // the request
            HttpRequestMessage message = new HttpRequestMessage();

            content.Add(new StreamContent(fileStream), "file", fileName);


            message.Method = HttpMethod.Post;
            message.Content = content;
            message.RequestUri = new Uri("http://localhost/UploadFileNoSecurity/upload/movie");


            var client = HttpClientFactory.Create(progress);
            client.Timeout = TimeSpan.FromHours(1);

            var response = await client.SendAsync(message);

            if (response.IsSuccessStatusCode)
            {
                Task httpResponse = response.Content.ReadAsStringAsync();
                List json = JsonConvert.DeserializeObject>(httpResponse.Result);
                return json;

            }

            return null;            
        }

    }

The DTO code

namespace UploadModel
{
    public class FileUploadModel
    {
     
        public string FileName { get; set; }

     
        public string LocalFullPath { get; set; }

     
        public string Comment { get; set; }
    }
}

Wednesday, November 4, 2015

C# Indexer not using the propertyItem

C# will use the property item when using indexers, but if you already have a property with that name you will have problem. To solve it use the attribute on your indexer with another name [IndexerName("MyItem")]

Friday, October 30, 2015

Specflow - how to create steps in another assembly

For some reason having steps in another assembly doesn't always work. When I tried this I found out there is a bug with specflow, that if you don't put your step class in the root of the assembly, it might not bind it correctly. So, place your step class directly in the root (not in a sub-folder). Also, in the app.config of your project with your feature files you need to have this configuration

Friday, March 20, 2015

Testing internal classes with C# and MSTest

put an attribute in the assemblyinfo.cs file in the project under test, pointing to the test assembly Project under test will have
[assembly: InternalsVisibleTo("MyTest")]

Thursday, June 26, 2014

How to make Alerts fade in and fade out with Bootstrap 3.0

I wanted to make the alerts work a little nicer by using fade in and fade out. I know there are classes in the CSS to handle the fade in, but they don't work in all browsers. So I wanted to implement some Javascript to make it work

Create a div for your alerts

<div id="alerts">

</div>

We need to create unique Ids, I have used this function to do so

   function createUUID() {
        // http://www.ietf.org/rfc/rfc4122.txt
        var s = [];
        var hexDigits = "0123456789abcdef";
        for (var i = 0; i < 36; i++) {
            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
        }
        s[14] = "4";  // bits 12-15 of the time_hi_and_version field to 0010
        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);  // bits 6-7 of the clock_seq_hi_and_reserved to 01
        s[8] = s[13] = s[18] = s[23] = "-";

        var uuid = s.join("");
        return uuid;
    }

Make a function to show the alert, by adding it dynamically

    function addAlert(message) {
        var id = createUUID();
        var JQueryId = "#" + id;

        $('#alerts').append(
            '');

        $(JQueryId).fadeIn(5000);
        window.setTimeout(function () {

            // closing the popup
            $(JQueryId).fadeTo(300, 0.5).slideUp(2000, function () {
                $(JQueryId).alert('close');
            });


        }, 10000);
    }

Notice that when adding the alert, it is hidden. The JQuery fadeIn API will create the fade effect when the alert is showing. Using setTimeout, we start fading out, and then closing the alert. You can play with the numbers to have the effect you want, but this seems to work nice and make alerts popup nice, and close on their own

Testing the Alerts

    $(document).ready(function () {

        addAlert("test");

        window.setTimeout(function () {
            addAlert("test1");
        }, 1000);

        window.setTimeout(function () {
            addAlert("test2");
        }, 10000);

        window.setTimeout(function () {
            addAlert("test3");
        }, 20000);

        window.setTimeout(function () {
            addAlert("test4");
        }, 20000);


        
    });

The code

You can see the code and the full effect here http://www.bootply.com/Sfn68ySAnB

Wednesday, June 18, 2014

Membership and roles as a WCF service

In case you want to have your membership and roles exposed as a service

Click here for more information

How to create a web thumbnail

I found a lot of tools that do this but I think the one I am going to really give a try is this one

webthumbnail.org

And I am going to try to add a link to CNN here:

Generated by WebThumbnail.org