This is one of the weird issue I have seen and here are the steps to reproduce
1> Create new Web API project in VS 2017 with Target Framework 4.6.2
Create new ASP.NET Web Application -> Select Empty -> Check Web API -> Click OK
2> Add Controller that returns a Stream
public class ReportController : ApiController
{
[HttpGet]
public HttpResponseMessage Download()
{
var filePath = "C:\\Report.xlsx";
var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(fs)
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
return result;
}
}
3> Run the application and invoke the api in IE 11 (use correct port #)
http://localhost:40005/api/report/download
The browser should download a EXCEL file and you should be able to open EXCEL file.
5> Stop Visual Studio
5> In the same solution create a new project with target framework .NET Standard 1.6
6> In the Web API Project, add project reference to newly created NET Standard library project
7> Run the application and invoke api in IE 11
http://localhost:40005/api/report/download
Notice that browser will get json back instead of excel file.
{"Version":{"_Major":1,"_Minor":1,"_Build":-1,"_Revision":-1},"Content":{"Headers":[{"Key":"Content-Type","Value":["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]}]},"StatusCode":200,"ReasonPhrase":"OK","Headers":[],"RequestMessage":null,"IsSuccessStatusCode":true}
If you try with google chrome then instead of json I get exception
Type 'System.Net.Http.StreamContent' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
I don't know why just by referencing .NET Standard 1.6
project changes the behavior. If I remove the reference to .NET Standard 1.6
project then everything works fine.
Is this a bug .NET?
What is the solution? Because i wanted to create a library that can be shared between classic .NET 4.6.2 and .NET Core projects. and i thought .NET Standard 1.6 is way to go
Update1
When i tried @Nkosi suggestion i get the exception below
HTTP/1.1 500 Internal Server Error Cache-Control: no-cache Pragma: no-cache Content-Type: application/json; charset=utf-8 Expires: -1 Server: Microsoft-IIS/10.0 X-AspNet-Version: 4.0.30319 X-SourceFiles: =?UTF-8?B?QzpcTXlQcm9qZWN0c1xXZWJBcHBsaWNhdGlvbjFcV2ViQXBwbGljYXRpb24xXGFwaVxyZXBvcnRcZG93bmxvYWQ=?= X-Powered-By: ASP.NET Date: Sat, 10 Feb 2018 02:02:47 GMT Content-Length: 1937
{"Message":"An error has occurred.","ExceptionMessage":"Method not found: 'System.Web.Http.Results.ResponseMessageResult System.Web.Http.ApiController.ResponseMessage(System.Net.Http.HttpResponseMessage)'.","ExceptionType":"System.MissingMethodException","StackTrace":" at WebApplication1.Controllers.ReportController.Download()\r\n at lambda_method(Closure , Object , Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.b__9(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()"}
Update 2
I lowered down NET Standard version to 1.4 and it worked. However then I changed Web Api project's package management format from package.config
to PackageReference
and restored all the packages. ( Why? missing dependencies issue)
and again API started returning JSON