0
votes

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.

1
Check your IIS Web log(s) to see if you are getting any hidden errors.SteveFerg
Can you locate the uploaded file anywhere on the machine?Ruard van Elburg
@SteveFerg updated the w3c log file content. I don't see any other error.Gopi
@RuardvanElburg I cannot find the file on my machine.Gopi

1 Answers

2
votes

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.