Reputation: 2702
I have requirement that I want a WCF service library that provide a PDF via REST.
For example I have an url like this: localhost:8732/service1/reports/ok
And I get a PDF as response. It is a fixed file in local filesystem.
Here it is my current code:
Service.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfJsonRestService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class Service1 : IService1
{
public Stream GetReport(string value)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/pdf";
FileStream f = new FileStream("C:\\invoice.pdf", FileMode.Open);
int length = (int)f.Length;
WebOperationContext.Current.OutgoingResponse.ContentLength = length;
byte[] buffer = new byte[length];
int sum = 0;
int count;
while ((count = f.Read(buffer, sum, length - sum)) > 0)
{
sum += count;
}
f.Close();
return new MemoryStream(buffer);
}
}
}
IService.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace WcfJsonRestService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IService1
{
// TODO: Add your service operations here
[OperationContract(Action = "*")]
[WebInvoke(Method = "GET", //Este metodo si esta en POST, te dice que metodo no permitido
UriTemplate = "reports/{value}")]
Stream GetReport(string value);
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
// You can add XSD files into the project. After building the project, you can directly use the data types defined there, with the namespace "WcfJsonRestService.ContractType".
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="WcfJsonRestService.Service1">
<endpoint address="http://localhost:8732/service1"
binding="webHttpBinding"
contract="WcfJsonRestService.IService1"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.1" sku=".NETFramework,Version=v4.1"/>
</startup>
</configuration>
Please, don't pay attention to that misleading name "WcfJsonRestService" that name will be changed later to a more properly one...
Everything is fine when I run this in Visual Studio 2013 (except a warning from Microsoft WCF Service Host that doesn't find any service metadata). When I visit http://localhost:8732/service1/somerandomstring the pdf is opened by the browser. (please note it is a fixed directory on my filesystem for the moment...)
The problem is when I try publish or host . I followed several tutorials about hosting in IIS with no success. How I should do to make this working?
OS: Windows 8.1 .NET Framework 4
Upvotes: 2
Views: 6050
Reputation: 9564
I stumbled upon this issue a couple days ago: it was due to the missing handler mapping which is required to hanle this type of call. There are several ways to work around the problem, such as manually execute the ServiceModelReg.exe
console command. The resolution method I propose below is more complex, but it has the advantage of fixing that specific issue without changing the default behavior of the web server, thus avoding potential side-effects.
Once the installation is complete, you should be able to run your WCF Service without incurring in the 404 error ever again.
For additional info regarding this specific issue and how to fix it, you can also read this post on my blog.
Upvotes: 5
Reputation: 592
I have tried to populate the problem on my machine and I got it. I found the solution as well. After hosting in IIS. The url you visit to hit the service will be http://localhost/<name of the site while hosting to iis>/<namespaceofyourservice>.<servicename>/<method name>
.
So for my case it became http://localhost/WcfJSONPDF/WcfJsonRestService.Service1.svc/reports/ok
. Here "ok" is the string passed to the web method.
I know its strange that we have to pass namespace as well in the url but you have to accept it for now. I will look for some workaround. Here is the Image of url definition : .
Here is steps to publish your Wcf Service Library
Project to IIS7. Please see below Image :
Click on Build-->Publish Webservice-->Name the url(website name)-->Click on publish button-->Click publish on Local IIS
.
Thats all. I hope you will get the desired output.
If you still have some issues then update App.config
with the below one:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service name="WcfJsonRestService.Service1" behaviorConfiguration="Metadata">
<endpoint address=""
binding="webHttpBinding"
contract="WcfJsonRestService.IService1" behaviorConfiguration="Restbeh"/>
<endpoint name="mex"
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:80/service1" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="Restbeh">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Metadata">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.1" sku=".NETFramework,Version=v4.1"/>
</startup>
</configuration>
Upvotes: 2
Reputation: 13349
Could be a permission issue, when hosting in IIS you need to give read permission to the identity that your site is running under to that folder and its contents. Which identity you're running under will depend on which version of IIS you're using and how you've configured your app pool. You can check which identity it is by looking at the advanced settings of your app pool and scrolling down to identity. Then check the security settings on your pdf folder for this user.
Upvotes: 0