0

The below code works very well on development environment VS 2012, the images are saved to App_Data.

When I deployed the same on Win 8.1, IIS 8.5, the App_Data was missing. I manually create the folder and set the properties as given in http://hintdesk.com/tutorial-publish-asp-net-web-api-in-iis-8-5-and-windows-8-1/.

I am seeing strange behavior as the upload is not consistent. Now and then the upload fails. Not sure why.

The application is hosted on same machine in which the development is done and the port # on IIS is set to same development port#

    [HttpPost]
    [Route("v1/persons/{personId}/image")]
    public IHttpActionResult CreatePersonImage(int personId)
    {
        if (Request.Content.IsMimeMultipartContent())
        {
            var isUpdated = 0;
            Request.Content.ReadAsMultipartAsync<MultipartMemoryStreamProvider>(new MultipartMemoryStreamProvider()).ContinueWith((task) =>
            {
                MultipartMemoryStreamProvider provider = task.Result;
                foreach (HttpContent content in provider.Contents)
                {
                    Stream stream = content.ReadAsStreamAsync().Result;
                    Image image = Image.FromStream(stream);
                    //var testName = content.Headers.ContentDisposition.Name;
                    var imageFileFullName = Utils.GetImageFileFullName(personId + ".jpg");
                    image.Save(imageFileFullName);
                    PersonDb persondb = new PersonDb();
                    isUpdated = persondb.CreatePersonImage(new Person()
                    {
                        ImageFileName = Path.GetFileName(imageFileFullName),
                        PersonId = personId
                    }, out InternalServerErr);
                }
            });
            return Ok();
        }
        else
        {
            return BadRequest("Error in Content-type. It should be multipart/form-data");
        }
    }

public static string GetImageFileFullName(string imageFileName)
{
    return Path.Combine(HostingEnvironment.MapPath("~/App_Data"), imageFileName);
}

Web config on IIS 8.5

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please     
visit
http://go.microsoft.com/fwlink/?LinkId=301879
-->
<configuration>
<appSettings>
</appSettings>
<system.web>
<compilation targetFramework="4.5">
  <assemblies>
    <add assembly="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  </assemblies>
</compilation>
<httpRuntime targetFramework="4.5" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
<connectionStrings>
<add name="Conn" connectionString="Server=localhost;Database=sampledb;User Id=sa; Password=test123"></add>
</connectionStrings>
</configuration>

The application always returns the 200 OK status but I don't see the file on App_Data on IIS.

W3C Log

#Fields: date time s-ip cs-method cs-uri7-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Referer) sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken CutomType CotentLength
2015-06-10 10:27:52 192.168.10.22 POST /v1/persons/4/image - 50737 - 192.168.10.22 RestSharp/105.1.0.0 - 200 0 0 210 6198 95 multipart/form-data;+boundary=-----------------------------28947758029299 5830

The size of the files are in few KBs

Edit: The problem seems to be with async so I followed https://stackoverflow.com/a/20356591/2922388 to upload synchronously and it worked fine.

Community
  • 1
  • 1
Gopi
  • 5,656
  • 22
  • 80
  • 146

1 Answers1

2

I think the reason you always get 200 OK is because the file is handled in an async task. So the task is started and 200 OK is returned. Any error on handling the file is lost because the request is already closed.

To catch the error you can log exceptions in the task to the database. Or remove the task and save the file not async. In that case I think you will get the error and not 200 OK.

The reason why no file is written has probably to do IIS since it works on a developer machine. One reason may be that files may not be saved inside inetpub. So create a folder outside inetpub and try again.

Another reason may be that IIS has insufficient rights. In that case set rights on the folder in explorer for the process running IIS.

-- EDIT --

I re-read your question. If it sometimes fails that suggests that IIS can write to the folder.

In that case it may have to do with the async filesave. Perhaps the stream is closed or incomplete.

  • Thanks. let me try and let you know. – Gopi Jun 10 '15 at 11:17
  • Any insights on how to test that? – Gopi Jun 10 '15 at 11:28
  • If it has to do with async filesave then I would add try-catch inside the task and log any exception to the database. Is there one file that allways fails? –  Jun 10 '15 at 11:43
  • No, I tried uploading the same fie again and again. – Gopi Jun 10 '15 at 11:53
  • So there is no pattern? Sometimes a file is saved and sometimes it fails? In that case I think you'll have to wait until it occurs again. But at least you'll know what the error is since it is logged in the database. –  Jun 10 '15 at 12:11
  • I am trying by removing the async and uploading the file synchronously. Will let you know the result – Gopi Jun 10 '15 at 12:19
  • I followed http://stackoverflow.com/a/20356591/2922388 and it works fine now. The problem is with async I think. – Gopi Jun 10 '15 at 12:31
  • Thanks for helping me to narrow down the issue. – Gopi Jun 10 '15 at 12:41