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.
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'm having some difficulties getting SwaggerWCF to load my documentation page, and I'm not sure why. I get no errors, but I also get no Swagger docs either, just a 404 when I visit http://localhost:8733/docs per the endpoint configuration. What am I doing wrong here? I have everything decorated up, using Framework 4.8. Service works fine and the mex and js endpoints will return data, just no swaggerUI.
Here is my App.Config:
<system.serviceModel>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" contentTypeMapper="Microsoft.Samples.WebContentTypeMapper.JsonContentTypeMapper, JsonContentTypeMapper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</webHttpEndpoint>
</standardEndpoints>
<services>
<service name="AutodeskVaultAPI.VaultWorker">
<endpoint address="" binding="basicHttpBinding" contract="AutodeskVaultAPI.IVaultServices">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="js" behaviorConfiguration="jsonEP" binding="webHttpBinding"
name="jsonEP" contract="AutodeskVaultAPI.IVaultServices" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/AutodeskVaultAPI/" />
</baseAddresses>
</host>
</service>
<service name="SwaggerWcf.SwaggerWcfEndpoint">
<endpoint address="http://localhost:8733/docs" binding="webHttpBinding" contract="SwaggerWcf.ISwaggerWcfEndpoint" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="jsonEP">
<webHttp helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Here is my service implementation:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[SwaggerWcf("/AutodeskVaultAPI/js")]
public class VaultWorker : IVaultServices
{
...[redacted]...
[SwaggerWcfTag("AutodeskVaultAPI")]
public AutodeskVaultFolder GetRootFolder(string vaultServerName = "", string currentUserLogin = "false")
{
try
{
Folder rootFolder = VaultConnection.WebServiceManager.DocumentService.GetFolderRoot();
if (null == rootFolder)
return null;
else
{
var toReturn = new AutodeskVaultFolder()
{
Created = rootFolder.CreateDate,
Category = (null == rootFolder.Cat) ? "No Category" : rootFolder.Cat.CatName,
CreatedByUserID = rootFolder.CreateUserId,
CreatedByUserName = rootFolder.CreateUserName,
EntityMasterID = rootFolder.Id,
FolderEntityName = rootFolder.Name,
FolderFullPath = rootFolder.FullName,
IsVaultRoot = true,
NumberOfChildren = rootFolder.NumClds,
ParentID = rootFolder.ParId
};
return toReturn;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
return null;
}
}
[SwaggerWcfTag("AutodeskVaultAPI")]
public AutodeskVaultSearchResponse SearchVault(AutodeskVaultSearchRequest request)
{
try
{
string bookMark = string.Empty;
var parameters = getSearchParametersFromRequest(request);
SrchStatus srchStatus = null;
List<File> foundFiles = new List<File>();
if (null != parameters && parameters.Length > 0)
{
while (null == srchStatus || foundFiles.Count < srchStatus.TotalHits)
{
File[] srcResults = VaultConnection.WebServiceManager.DocumentService.FindFilesBySearchConditions(parameters, null, null, true, false, ref bookMark, out srchStatus);
if (null != srcResults)
foundFiles.AddRange(srcResults);
else
break;
}
}
return mapResultsToResponse(request, foundFiles);
}
catch (Exception ex)
{
Debug.Write(ex);
return null;
}
}
...[redacted]...
[DataContract(Name = "AutodeskVaultSearchRequest")]
public class AutodeskVaultSearchRequest
{
[DataMember]
public bool OR_Search = false;
[DataMember]
public List<AutodeskVaultProperty> properties;
}
[DataContract(Name = "AutodeskVaultSearchResponse")]
public class AutodeskVaultSearchResponse
{
[DataMember]
public AutodeskVaultSearchRequest Request;
[DataMember]
public List<AutodeskVaultFile> Files;
[DataMember]
public string Message;
and here is my service interface:
[ServiceContract]
public interface IVaultServices
{
[SwaggerWcfPath("GetRootFolder", #"Test the default configured server to see if we can get back the root folder")]
[OperationContract]
[WebInvoke(UriTemplate = "GetRootfolder/{vaultServerName}/{currentUserLogin}", Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
[Description(#"Test the default configured server to see if we can get back the root folder")]
AutodeskVaultFolder GetRootFolder(string vaultServerName = "", string currentUserLogin = "false");
[SwaggerWcfPath("GetAsbuiltDrawingsByNumber", #"Given an Autodesk Search Request, search through Vault to find File information using the supplied properties.")]
[OperationContract]
[WebInvoke(UriTemplate = "SearchVault", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
[Description(#"Given an Autodesk Search Request, search through Vault to find File information using the supplied properties.")]
AutodeskVaultSearchResponse SearchVault(AutodeskVaultSearchRequest request);
}
Add an endpoint to your App.config file.
<services>
<service name="SwaggerWcf.SwaggerWcfEndpoint">
<endpoint address="http://localhost/docs" binding="webHttpBinding" contract="SwaggerWcf.ISwaggerWcfEndpoint" />
</service>
</services>
Create a WebServiceHost
var swaggerHost = new WebServiceHost(typeof(SwaggerWcfEndpoint));
swaggerHost.Open();
You can refer to the steps provided in the link for details.
https://github.com/abelsilva/swaggerwcf
How do I view my Swagger docs when using SwaggerWcf?
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.
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 creating a WCF service with self hosting. I have found the following error i.e.:
The target assembly contains no service types. You may need to adjust the Code Access Security policy of this assembly.
The codes are as follows:
namespace MyJobs
{
public interface IJobsSvc
{
[OperationContract]
DataSet GetJobs();
[OperationContract]
Job GetJobInfo(int JobId);
[OperationContract]
List<Job> GetAllJobs();
}
}
namespace MyJobs
{
[DataContract]
public class Job
{
[DataMember]
public int JobId { get; set;}
[DataMember]
public string Description{get;set;}
[DataMember]
public int MinLevel { get; set; }
[DataMember]
public int MaxLevel { get; set; }
}
}
namespace MyJobs
{
public class JobsSvc:IJobsSvc
{
#region IJobsSvc Members
public System.Data.DataSet GetJobs()
{
string str = #"data source=PERSONAL-659BE4;database=practice;integrated security=true";
DataSet ds = new DataSet();
SqlConnection cn = new SqlConnection(str);
SqlDataAdapter da = new SqlDataAdapter("select * from Job1",cn);
da.Fill(ds);
return ds;
}
public Job GetJobInfo(int JobId)
{
string str = #"data source=PERSONAL-659BE4;database=practice;integrated security=true";
SqlConnection cn = new SqlConnection(str);
SqlCommand cmd = new SqlCommand("select * from Job1 where JobId="+JobId,cn);
cn.Open();
SqlDataReader dr = cmd.ExecuteReader();
Job obj = new Job();
if (dr.Read())
{
obj.JobId = JobId;
obj.Description = dr[1].ToString();
obj.MinLevel = Convert.ToInt32(dr[2]);
obj.MaxLevel = Convert.ToInt32(dr[3]);
}
else
{
obj.JobId = -1;
}
return obj;
}
public List<Job> GetAllJobs()
{
throw new NotImplementedException();
}
#endregion
}
}
The app.config file is:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<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="MyJobs.Job">
<endpoint address="" binding="wsHttpBinding" contract="MyJobs.IJobsSvc">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/Jobs/MyJobs/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
You need to add [ServiceContract] attribute to your IJobSvc interface
Update
Create the behavior to expose the metadata.
<serviceBehaviors>
<behavior name="SimpleServiceBehavior">
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
Then configure your service with this behavior:
<service name="MyJobs.Job" behaviorConfiguration="SimpleServiceBehavior">
<endpoint address="" binding="wsHttpBinding" contract="MyJobs.IJobsSvc">