mshouman
mshouman

Reputation: 384

Sending file from MVC application to Web API performance

My solution has two projects one ASP.NET MVC (as UI only) and ASP.NET Web API (as Restful service). I want to send the uploaded files from MVC project to Web API and on deployment each application will be hosted on different server so I need all files to be centralized in Web API server. I need help to compare between two options (performance aspect) for doing that:

1- Send the uploaded file from MVC action to Web API Post action like this:

In MVC Project:

    [HttpPost]
    public ActionResult UploadProfilePicture(HttpPostedFileBase file)
    {
        using (var client = new HttpClient())
        {
            using (var content = new MultipartFormDataContent())
            {
                byte[] Bytes = new byte[file.InputStream.Length + 1];
                file.InputStream.Read(Bytes, 0, Bytes.Length);
                var fileContent = new ByteArrayContent(Bytes);
                fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = file.FileName };
                content.Add(fileContent);
                var requestUri = "http://localhost:1963/api/upload";
                var result = client.PostAsync(requestUri, content).Result;
                if (result.StatusCode == System.Net.HttpStatusCode.Created)
                {
                    List<string> m = result.Content.ReadAsAsync<List<string>>().Result;
                    ViewBag.Success = m.FirstOrDefault();

                }
                else
                {
                    ViewBag.Failed = "Failed !" + result.Content.ToString();
                }
            }
        }
        return View();
    }

In Web API Project:

    public HttpResponseMessage Post()
    {
        HttpResponseMessage result = null;
        var httpRequest = HttpContext.Current.Request;
        if (httpRequest.Files.Count > 0)
        {
            var docfiles = new List<string>();
            foreach (string file in httpRequest.Files)
            {
                var postedFile = httpRequest.Files[file];
                var filePath = HttpContext.Current.Server.MapPath("~/" + postedFile.FileName);
                postedFile.SaveAs(filePath);
                docfiles.Add(filePath);
            }
            result = Request.CreateResponse(HttpStatusCode.Created, docfiles);
        }
        else
        {
            result = Request.CreateResponse(HttpStatusCode.BadRequest);
        }
        return result;
    }

2- Send the uploaded file from MVC action to Web API Server like this:

System.IO.File.Copy("sourcePath in MVC server", "\\machinename\share folder path");

What is the best performance?

Upvotes: 1

Views: 2872

Answers (2)

sabotero
sabotero

Reputation: 4365

In option 1, you are uploading the file two times: From client to the server where the MVC application it's hosted, then from there to your Web API.

In Option 2 seems best in performance only with respect of the uploading, as you are calling directly the Web Api from the client.

But as always it depends on what you want to achieve.

You should use the browser (firefox or chrome) profiler to compare the time that each option takes.

Whenever you have doubts about performance you should profile your application. Also remember that performance is a feature.

You can use this tools for different cases of profiling [1]:

Discover hot spots in the code

Discover allocations in the code

Do both

  • Performance Explorer (Visual Studio)
  • PerfView (watch channel9 videos on how to use!)

Isolate a function and iterate improvements

[1] Tooling proposed by Ben Adams

Upvotes: 3

Markus
Markus

Reputation: 22456

I suspect that option 2 with direct file access should provide a better performance, because the protocol that is used is optimized for transferring binary files whereas the HTTP protocol serves different purposes.

However, performance should not be the sole criteria on choosing the solution. If you choose between the options, you also need to evaluate other implications.

From an architectural and security point of view, option 2 is worse than option 1, because:

  • The coupling of the two parts of the application is tighter. As an example: at a later point in time, you might decide that you want to store the files not in the file system, but on cloud storage. For option 2 you'd have to change both the MVC application and the Web API. For option 1, only the inner workings of the Web API.
  • Also, you always have to run the applications in an environment where the MVC server can access the Web API server by file access protocol. This requires a great amount of control over the system and there are environments where you do not have that much control over the systems (e.g. cloud PaaS). These environments might not be relevant now, but might be in the future.
  • In terms of security, you have to allow the MVC application to write to a share of the Web API server. For sure, you have already secured your Web API from unauthorized access. For option 2, you'd need to open another door to your application. This increases the risk of attacks and also the effort that is needed to deploy the application.

For these reasons, I'd opt for option 1 as long as the performance is good enough for your requirements.

As an alternative, you could also upload the file from the client to the Web API directly and therefore reduce the number of uploads you have to do.

Upvotes: 4

Related Questions