I am getting this error:
No Model instance has been assigned to the ProtoOperationBehavior
I just used the WCF template application in Visual Studio to see if I could get it running. How do I fix this error?
Code
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
[ServiceContract]
public interface IService1
{
[OperationContract]
[ProtoBehavior()]
string GetData(int value);
[OperationContract]
[ProtoBehavior()]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
[DataContract]
[ProtoBuf.ProtoContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember(Order = 1)]
[ProtoBuf.ProtoMember(1)]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember(Order = 2)]
[ProtoBuf.ProtoMember(2)]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
app.config:
<services>
<service name="ProtoBufService.Service1">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:9086/ProtoBufService/Service1/" />
</baseAddresses>
</host>
<endpoint address="basic"
binding="netTcpBinding" contract="ProtoBufService.IService1"
behaviorConfiguration="protoEndpointBehavior">
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
</service>
</services>
<extensions>
<behaviorExtensions>
<add name="protobuf"
type="ProtoBuf.ServiceModel.ProtoBehaviorExtension,
protobuf-net, Version=2.0.0.640,
Culture=neutral, PublicKeyToken=257b51d87d2e4d67" />
</behaviorExtensions>
</extensions>
<endpointBehaviors>
<behavior name="protoEndpointBehavior">
<protobuf />
</behavior>
</endpointBehaviors>
I tried using nuget. That did not work.
I would love to hear more about what problems you had there
I then tried to use the google code version (Core, net30 assembly), same error.
The "core only" library does not include the meta-programming layer - it is designed for use with pre-generated serialization assemblies. As such, there is no default model - one must always be provided.
The simplest "fix" here is simply to use the "full" build of the library; this has the meta-programming model as a default model.
Related
I'm trying to assemble a .Net 6 WCF Service with WCFCore, using a basicHttpBinding, and I'm strugling to add a service authorization manager.
My purpose is to enable WCF to read and validate bearer tokens and use OAuth. I can't move to REST because of legacy applications compatibility, so I need to keep WCF but use bearer tokens.
My service at this stage is quite simple:
[ServiceContract]
public interface IService
{
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
public class Service : IService
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
[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; }
}
}
My Program.cs:
var builder = WebApplication.CreateBuilder();
builder.Services.AddServiceModelServices();
builder.Services.AddServiceModelConfigurationManagerFile("wcf.config");
builder.Services.AddServiceModelMetadata();
builder.Services.AddSingleton<IServiceBehavior, UseRequestHeadersForMetadataAddressBehavior>();
builder.Services.AddSingleton<OAuthAuthorizationManager>();
var app = builder.Build();
app.UseServiceModel(bld =>
{
bld.AddServiceEndpoint<Service, IService>(new BasicHttpBinding(BasicHttpSecurityMode.Transport), "/Service.svc");
var mb = app.Services.GetRequiredService<ServiceMetadataBehavior>();
mb.HttpsGetEnabled = true;
});
app.Run();
Then my wcf.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicBinding" receiveTimeout="00:10:00">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="CoreWCFService.Service" behaviorConfiguration="Default">
<endpoint address="basic" binding="basicHttpBinding" bindingConfiguration="basicBinding" contract="CoreWCFService.IService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
<serviceAuthorization serviceAuthorizationManagerType="CoreWCFService.OAuthAuthorizationManager,CoreWCFService" />
<dataContractSerializer maxItemsInObjectGraph="10000000" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
But when I call the service with tokens, nothing happens on the authorization manager, the operation runs simply ignoring this service behavior.
Is there anyone out there that can help me with this?
You may refer to the Corewcf project template. There are a few things to note:
The interface and its implementation need to be separated to facilitate subsequent maintenance and invocation of the interface.
We need to look at the UseServiceModel part in Program.cs.
I am trying to get my first WCF restful service to work. But I keep getting a warning when i run it through VS2013. it says it cannot find any service metadata.
How do i set this up?
The App.config file is as follows,
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<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>
</configuration>
The IService1.cs
namespace WcfJsonRestService
{
[ServiceContract]
public interface IService1
{
[OperationContract]
Service1.Person GetData(string id);
}
}
The Service1.cs
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.
public class Service1 : IService1
{
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "data/{id}")]
public Person GetData(string id)
{
// lookup person with the requested id
return new Person()
{
Id = Convert.ToInt32(id),
Name = "Leo Messi"
};
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
}
}
I have a service contract defined as:
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://www.ans.gov.br/tiss/ws/tipos/tisscancelaguia/v30001", ConfigurationName = "ItissCancelaGuia")]
public interface ItissCancelaGuia
{
[System.ServiceModel.OperationContractAttribute(Action = "tissCancelaGuia", ReplyAction = "*")]
[System.ServiceModel.FaultContractAttribute(typeof(tissFaultWS), Action = "", Name = "tissFaultWS", Namespace = "http://www.ans.gov.br/padroes/tiss/schemas")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults = true)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(SignatureType))]
mensagemTISS tissCancelaGuia_Operation(string mensagem);
}
And the implementation:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single, ConfigurationName = "CancelaGuiaTS")]
public sealed class tissCancelaGuia : ItissCancelaGuia
{...}
and also the relevant parts of the web.config:
<service behaviorConfiguration="tissCancelaGuiaStringServiceBehavior"
name="CancelaGuiaTS">
<endpoint address="" behaviorConfiguration="EndPointValidation"
binding="basicHttpBinding" bindingConfiguration="TISSv3_binding"
name="CancelaGuiaTs" contract="ItissCancelaGuia" />
<endpoint address="mex" binding="mexHttpBinding" name="CancelaGuiaTsMetadata"
contract="IMetadataExchange" />
</service>
and
<behavior name="tissCancelaGuiaStringServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
The service compiles correctly but the wsdl exposed contains no operations.
The only solution I can think of is to write the wsdl manually and expose it through the externalMetadataLocation attibute of the serviceMetadata, but it just don't feel right to me.
Edit 1
Here the definition of the mensagemTISS class
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.ans.gov.br/padroes/tiss/schemas")]
public partial class mensagemTISS
{ ... }
Don't know if it is important but the class have this property:
[System.Xml.Serialization.XmlElementAttribute("operadoraParaPrestador", typeof(operadoraPrestador), Order=1)]
[System.Xml.Serialization.XmlElementAttribute("prestadorParaOperadora", typeof(prestadorOperadora), Order=1)]
public object Item
{
get
{
return this.itemField;
}
set
{
this.itemField = value;
}
}
defined as a choice in the originating schema.
I have a service with below code
TaskService.svc
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class TodoService : ITodoService
{
private readonly List<Todo> _dataSource;
public TodoService()
{
_dataSource = new List<Todo>();
}
[WebGet(UriTemplate = "/Todos")]
public List<Todo> Todos()
{
return _dataSource;
}
}
and the data transfer object is as below
[ServiceContract]
public interface ITodoService
{
[OperationContract]
List<Todo> Todos();
}
[DataContract]
public class Todo
{
[DataMember]
public string Name { get; set; }
[DataMember]
public bool Completed { get; set; }
}
the web.config as below
<services>
<service name="SampleService.TodosBehavior">
<endpoint address="" behaviorConfiguration="SampleService.TodosBehavior"
binding="webHttpBinding" contract="SampleService.TodoService" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="SampleService.TodosBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
the application is hosted in IIS 7 with virtual directory SampleService. When ever i invoke using browser http://localhost/SampleService/TaskService.svc/Todos i am greeted with nothing. But i expected a empty array. Why is this so?
I think the WebGet() needs to be in your interface (ServiceContract) rather than your implementation of that interface. Also, do you need the slash before "Todos" in your UriTemplate?
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class TodoService : ITodoService
{
private readonly List<Todo> _dataSource;
public TodoService()
{
_dataSource = new List<Todo>();
}
public List<Todo> Todos()
{
return _dataSource;
}
}
[ServiceContract]
public interface ITodoService
{
[WebGet(UriTemplate = "Todos")]
[OperationContract]
List<Todo> Todos();
}
If you're hosting in IIS, what does your TaskService.svc file look like?
EDIT: Oh, this IS your .svc file. Never mind then.
I am just trying with various WCF(in .Net 3.0) scenarios.
I am using self hosting.
I am getting an exception as "Service 'MyServiceLibrary.NameDecorator' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element."
I have a config file as follows (which has an endpoint)
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="Lijo.Samples.NameDecorator"
behaviorConfiguration="WeatherServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8010/ServiceModelSamples/FreeServiceWorld"/>
</baseAddresses>
</host>
<endpoint address=""
binding="wsHttpBinding"
contract="Lijo.Samples.IElementaryService" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WeatherServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
And a Host as
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Runtime.Serialization;
namespace MySelfHostConsoleApp
{
class Program
{
static void Main(string[] args)
{
System.ServiceModel.ServiceHost myHost = new ServiceHost(typeof(MyServiceLibrary.NameDecorator));
myHost.Open();
Console.ReadLine();
}
}
}
My Service is as follows
using System.ServiceModel;
using System.Runtime.Serialization;
namespace MyServiceLibrary
{
[ServiceContract(Namespace = "http://Lijo.Samples")]
public interface IElementaryService
{
[OperationContract]
CompanyLogo GetLogo();
}
public class NameDecorator : IElementaryService
{
public CompanyLogo GetLogo()
{
CircleType cirlce = new CircleType();
CompanyLogo logo = new CompanyLogo(cirlce);
return logo;
}
}
[DataContract]
public abstract class IShape
{
public abstract string SelfExplain();
}
[DataContract(Name = "Circle")]
public class CircleType : IShape
{
public override string SelfExplain()
{
return "I am a Circle";
}
}
[DataContract(Name = "Triangle")]
public class TriangleType : IShape
{
public override string SelfExplain()
{
return "I am a Triangle";
}
}
[DataContract]
[KnownType(typeof(CircleType))]
[KnownType(typeof(TriangleType))]
public class CompanyLogo
{
private IShape m_shapeOfLogo;
[DataMember]
public IShape ShapeOfLogo
{
get
{
return m_shapeOfLogo;
}
set
{
m_shapeOfLogo = value;
}
}
public CompanyLogo(IShape shape)
{
m_shapeOfLogo = shape;
}
}
}
Could you please help me to understand what I am missing here?
Thanks
Lijo
You're self-hosting in a console app - how is your config set up??
Does your MySelfHostConsoleApp project have an app.config file?
Do you have the MySelfHostConsoleApp.exe.config in the same directory as the MySelfHostConsoleApp.exe file?
The error message just really means the config cannot be found and thus cannot be interpreted and used.
UPDATE: the other option is that WCF cannot interpret the config if it's present.
Check this out:
in your .NET code, your service class that implements the service is called MyServiceLibrary.NameDecorator
however, in your config, you call your service:
<service name="Lijo.Samples.NameDecorator"
That's not going to work! You're mixing up the .NET namespaces and the service namespaces here - and the name you need to put in your service-side config is the .NET fully qualified type name (including the .NET namespace - not the service namespace!).
Your service host will look for an entry <service name="MyServiceLibrary.NameDecorator"> based on your code - but it won't find it.
So you need to make sure to sync those two things up - the fully qualified service class name (including namespace and all) MUST match the name="...." attribute in your <service> tag in your config.