WCF service selfhosting - wcf

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">

Related

SwaggerWCF configuration for self hosted WCF library

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?

WCF Rest and Soap

I try to write simple subscription service with soap and rest operations. This is my code:
SubsService.svc:
namespace SubscriptionService
{
public class SubsService : ISubsService
{
public string RegisterEvent(string serviceId, string name, string description)
{
return "ok";
}
public void UnregisterEvent(string serviceId, string name)
{
// TO DO
}
public void RiseEvent(string serviceId, string name)
{
// TO DO
}
public string EventsList(string token)
{
return token;
}
public void Subscribe(string token, string serviceId, string name)
{
// TO DO
}
public void UnSubscribe(string token, string serviceId, string name)
{
// TO DO
}
}
}
ISubsService.cs:
namespace SubscriptionService
{
[ServiceContract]
public interface ISubsService
{
// SOA
[OperationContract]
string RegisterEvent(string serviceId, string name, string description);
[OperationContract]
void UnregisterEvent(string serviceId, string name);
[OperationContract]
void RiseEvent(string serviceId, string name);
// REST
[OperationContract]
[WebGet(UriTemplate = "events?token={token}")]
string EventsList(string token);
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "subscribe?token={token}&serviceId={serviceId}&name={name}")]
void Subscribe(string token, string serviceId, string name);
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "unsubscribe?token={token}&serviceId={serviceId}&name={name}")]
void UnSubscribe(string token, string serviceId, string name);
}
}
and web.config:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<services>
<service name="SubscriptionService.SubsService">
<endpoint address="soap" binding="basicHttpBinding" contract="SubscriptionService.ISubsService"></endpoint>
<endpoint address="rest" binding="webHttpBinding" contract="SubscriptionService.ISubsService" behaviorConfiguration="web"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="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>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
When I try to access http://localhost:2354/SubsService.svc, I get error:
Operation 'RegisterEvent' of contract 'ISubsService' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped.
But RegisterEvent has to be soap operation. What is wrong with my code? Something in web.config?

The caller was not authenticated by the service

I have build a simple WCF service using wsDualHttpBinding. It is working fine at local end but it throws a error when I publish the service on a different server and try to consume that service in a WPF project.
Error:
System.ServiceModel.SecurityNegotiationException "The caller was not authenticated by the service."
InnerException:
System.ServiceModel.FaultException "The caller was not authenticated by the service."
Server Config:
<system.serviceModel>
<services>
<service name="VetChat.Service.VetChatService" behaviorConfiguration="wsDualHttpBinding.SampleServiceBehavior">
<!-- Service Endpoints -->
<host>
<baseAddresses>
<add baseAddress="http://service.softprodigy.com:8090/VetChatService.svc"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsDualHttpBinding" contract="VetChat.Service.IVetChatService">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="VPS" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="wsDualHttpBinding.SampleServiceBehavior">
<!-- 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="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="VetChat.Service.UserNamePassValidator, VetChat.Service" />
<serviceCertificate findValue="MyName" storeLocation="CurrentUser" storeName="TrustedPeople" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Client Config:
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_IVetChatService" />
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="http://service.softprodigy.com:8090/VetChatService.svc"
binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IVetChatService"
contract="ServiceReference1.IVetChatService" name="WSDualHttpBinding_IVetChatService">
<identity>
<dns value="VPS" />
</identity>
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="MyName" x509FindType="FindBySubjectName"
storeLocation="CurrentUser" storeName="TrustedPeople" />
<serviceCertificate>
<defaultCertificate findValue="MyName" storeLocation="CurrentUser" storeName="TrustedPeople" x509FindType="FindBySubjectName" />
<authentication certificateValidationMode="PeerTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Interface:
[ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
public interface IVetChatService
{
[OperationContract(IsOneWay = true)]
void DoWork();
}
public interface ICallback
{
[OperationContract(IsOneWay = true)]
void Notify(string value);
}
Interface Implementation:
public class VetChatService : IVetChatService
{
public void DoWork()
{
//Thread.Sleep(5000);
OperationContext.Current.GetCallbackChannel<ICallback>().Notify("Hello");
}
}
Validte username password service class:
namespace VetChat.Service
{
class UserNamePassValidator :
System.IdentityModel.Selectors.UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName == null || password == null)
{
throw new ArgumentNullException();
}
if (!(userName == UserName && password == Password))
{
//throw new FaultException("Incorrect Username or Password");
}
}
}
public class Service
{
}
}
Call method:
InstanceContext instanceContext = new InstanceContext(new SampleServiceCallback());
ServiceReference1.VetChatServiceClient sampleServiceClient = new ServiceReference1.VetChatServiceClient(instanceContext);
sampleServiceClient.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.TrustedPeople,
X509FindType.FindBySubjectName,
"MyName");
sampleServiceClient.ClientCredentials.UserName.UserName = UserName;
sampleServiceClient.ClientCredentials.UserName.Password = Password;
//sampleServiceClient.Open();
sampleServiceClient.DoWork();
Response Callback:
public class SampleServiceCallback : ServiceReference1.IVetChatServiceCallback
{
#region ISampleServiceCallback Members
public void Notify(string value)
{
MessageBox.Show(value);
}
#endregion
}
Thanks

WCF windows service, Service metadata may not be accessible

Hi a have WCF service libary with this configuration:
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<services>
<service behaviorConfiguration="Default" name="ComDocs.ControlServerServiceLibary.Concrete.TokenService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/TokenService" />
</baseAddresses>
</host>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="basic" binding="basicHttpBinding" contract="ComDocs.ControlServerServiceLibary.Abstract.ITokenService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
If I build it in debug, everything works fine on localhost. But if I make a Windows Service library with the same configuration:
public partial class TokenService : ServiceBase
{
ServiceHost _host = null;
public TokenService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Trace.WriteLine("Starting Token Service...");
_host = new ServiceHost(typeof(TokenService));
_host.Open();
}
protected override void OnStop()
{
Trace.WriteLine("Shutting down Token Service...");
if (_host != null)
{
_host.Close();
_host = null;
}
}
}
Install it with InstallUtil and start it:
but error:
I suspect this line is the culprit.
_host = new ServiceHost(typeof(TokenService));
TokenService is your Windows service class, not your WCF service class.

Unable to run first WCF service

This is my first WCF service and I am getting an error:
Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.
Code:
namespace WcfMathServiceLibrary
{
[ServiceContract]
public interface IMath
{
[OperationContract]
double Add(double i, double j);
[OperationContract]
double Sub(double i, double j);
[OperationContract]
Complex AddComplexNo(Complex i, Complex j);
[OperationContract]
Complex SubComplexNo(Complex i, Complex j);
}
[DataContract]
public class Complex
{
private int _real;
private int _imaginary;
[DataMember]
public int real { get; set; }
[DataMember]
public int imaginary { get; set; }
}
namespace WcfMathServiceLibrary
{
public class MathService : IMath
{
public double Add(double i, double j)
{
return (i + j);
}
public double Sub(double i, double j)
{
return (i - j);
}
public Complex AddComplexNo(Complex i, Complex j)
{
Complex result = new Complex();
result.real = i.real + j.real;
result.imaginary = i.imaginary + j.imaginary;
return result;
}
public Complex SubComplexNo(Complex i, Complex j)
{
Complex result = new Complex();
result.real = i.real - j.real;
result.imaginary = i.imaginary - j.imaginary;
return result;
}
}
Web.Config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="WcfMathServiceLibrary.MathService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/WcfMathServiceLibrary/MathService/"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="WcfMathServiceLibrary.MathService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" >
</endpoint>
</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>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
I am not sure what is the issue. Could you please guide me?
I think your contract may need to point to the interface and not the concrete implementation
<endpoint address="" binding="wsHttpBinding" contract="WcfMathServiceLibrary.IMath">