So this is pretty new to me and I'm making progress. I currently have a wcf service using netmsmqbinding to send a simple message to a queue. Everything runs smooth and the event view even says that the message was put in the queue. Although when I goto the actual queue there is nothing in there. I have a service, service host, and asp web app. Note in the web app I have a service reference to the service. Also in the msmq log in the event viewer I get 3 events. Any assistance would be appreciated. Thanks.
Here's my setup.
Service Interface:
[ServiceContract]
public interface IMSMQService
{
[OperationContract(IsOneWay = true)]
void ShowMessage(string msg);
}
Service:
public class MSMQService : IMSMQService
{
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public void ShowMessage(string msg)
{
Debug.WriteLine(msg + " Received at: " + System.DateTime.Now.ToString());
}
}
App.Config of Service:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
<appSettings>
<!-- use appSetting to configure MSMQ queue name -->
<add key="queueName" value=".\private$\TestQueue"/>
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
<system.serviceModel>
<services>
<service name="MSMQNoSecurityService.MSMQService" behaviorConfiguration="MyBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9001/msmq"/>
</baseAddresses>
</host>
<endpoint address="net.msmq://localhost/private/TestQueue" binding="netMsmqBinding" bindingConfiguration="MyBinding" contract="MyService.IMSMQService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<serviceMetadata httpGetEnabled="True"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netMsmqBinding>
<binding name="MyBinding">
<security mode="None"/>
</binding>
</netMsmqBinding>
</bindings>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
Service Host
static void Main(string[] args)
{
ServiceHost svcHost = null;
try
{
// Get MSMQ queue name from appsettings in configuration.
string queueName = ConfigurationManager.AppSettings["queueName"];
// Create the transacted MSMQ queue if necessary.
if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName, true);
svcHost = new ServiceHost(typeof(MyService.MSMQService));
svcHost.Open();
Console.WriteLine("\n\nService is Running at following address");
Console.WriteLine("\nhttp://localhost:9001/MSMQService");
}
catch (Exception eX)
{
svcHost = null;
Console.WriteLine("Service can not be started \n\nError Message [" + eX.Message + "]");
}
if (svcHost != null)
{
Console.WriteLine("\nPress any key to close the Service");
Console.ReadKey();
svcHost.Close();
svcHost = null;
}
}
App.Config of Service Host:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
<appSettings>
<add key="queueName" value=".\private$\TestQueue"/>
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<services>
<service name="MyService.MSMQService" behaviorConfiguration="MyBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9001/msmq"/>
</baseAddresses>
</host>
<endpoint address="net.msmq://localhost/private/TestQueue" binding="netMsmqBinding" bindingConfiguration="MyBinding" contract="MyService.IMSMQService"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netMsmqBinding>
<binding name="MyBinding" >
<security mode="None"/>
</binding>
</netMsmqBinding>
</bindings>
</system.serviceModel>
</configuration>
MVC Controller
public class WcfMsmqController : Controller
{
public ActionResult Index()
{
MSMQServiceClient proxy = new MSMQServiceClient();
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
proxy.ShowMessage("test");
scope.Complete();
}
proxy.Close();
return View();
}
}
Service model in Web.config (autogenerated):
<system.serviceModel>
<bindings>
<netMsmqBinding>
<binding name="NetMsmqBinding_IMSMQService">
<security mode="None" />
</binding>
</netMsmqBinding>
</bindings>
<client>
<endpoint address="net.msmq://localhost/private/TestQueue" binding="netMsmqBinding"
bindingConfiguration="NetMsmqBinding_IMSMQService" contract="ServiceReference1.IMSMQService"
name="NetMsmqBinding_IMSMQService" />
</client>
</system.serviceModel>
Events from MSMQ Log: Modified some of it for viewing on here
Message with ID CN=msmq,CN=blah,OU=blah,OU=blah,DC=blah,DC=local\8280 was sent to queue PRIVATE=blah
Message with ID CN=msmq,CN=blah,OU=blah,OU=blah,DC=blah,DC=local\8280 was put into queue PRIVATE=blah
Message received
It seems to be related to your transaction.
You should try to place [TransactionFlow(TransactionFlowOption.Allowed)] on the operation in the service contract. Something like:
[ServiceContract]
public interface IMSMQService
{
[OperationContract(IsOneWay = true)]
[TransactionFlow(TransactionFlowOption.Allowed)]
void ShowMessage(string msg);
}
Anyway, you should be aware of local transactions if you decide to deploy this on web farm or something that involves multiple computers.
Figured it out. I had to add a namespace to the servicecontract. Prior it would default to some kind of tempuri.
[ServiceContract(Namespace = "http://MyService")]
public interface IMSMQService
{
[OperationContract(IsOneWay = true)]
[TransactionFlow(TransactionFlowOption.Allowed)]
void ShowMessage(string msg);
}
Related
I have a wcf project, very standard in first place.
The problem is when i Host it with Visual Studio, it works just fine
But when i host it with my custom made program, im getting errors.
System.Exception: Couldn't create ActiveX Component.
at Microsoft.VisualBasic.Interaction.GetObject(String PathName, String Class)
System.Runtime.Serialization.SerializationException: The type "DiskViewBox.DiskViewItem" in assembly "DiskViewBox, Version=1.0.3401.18107, Culture=neutral, PublicKeyToken=null" is not marked as serialisable.
I want to run it as a Windows Service later on.
I assume the problem is not in the client, because it works, and unfortunately i dont know how Visual Studio is hosting it, so i cant compare it to the custom Host.
using System.ServiceModel;
using System.ServiceModel.Description;
using WcfService1;
namespace WcfServiceHost
{
class Program
{
static void Main(string[] args)
{
// Step 1: Create a URI to serve as the base address.
Uri baseAddress = new Uri("net.tcp://localhost:7891/Test/WcfService1/Service1/");
// Step 2: Create a ServiceHost instance.
using (ServiceHost selfHost = new ServiceHost(typeof(Service1), baseAddress))
{
try
{
// Step 3: Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(IService1), new NetTcpBinding(), "IService1");
// Step 4: Enable metadata exchange.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
//smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
// Step 5: Start the service.
selfHost.Open();
Console.WriteLine("The service is ready.");
// Close the ServiceHost to stop the service.
Console.WriteLine("Press <Enter> to terminate the service.");
Console.WriteLine();
Console.ReadLine();
selfHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occurred: {0}", ce.Message);
selfHost.Abort();
}
}
}
}
}
The App.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
<system.web>
<compilation debug="true" />
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
<!-- Bei der Bereitstellung des Dienstbibliothekprojekts muss der Inhalt der Konfigurationsdatei der
app.config-Datei des Hosts hinzugefügt werden. System.Configuration unterstützt keine Konfigurationsdateien für Bibliotheken. -->
<system.serviceModel>
<services>
<service name="WcfService1.Service1">
<endpoint address="" binding="netTcpBinding" bindingConfiguration="" contract="WcfService1.IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:7891/Test/WcfService1/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
The client is written in VB because the access is from a VB environment and its easier to Debug in VS.
Module Module1
Sub Main()
Dim addr As String
addr = "service:mexAddress=""net.tcp://localhost:7891/Test/WcfService1/Service1/Mex"","
addr = addr + "address=""net.tcp://localhost:7891/Test/WcfService1/Service1/"","
addr = addr + "contract=""IService1"", contractNamespace=""http://tempuri.org/"","
addr = addr + "binding=""NetTcpBinding_IService1"", bindingNamespace=""http://tempuri.org/"""
Dim service1 As Object
MsgBox(addr)
Dim path As String
path = "C:\\tmp\\test1.docm"
service1 = GetObject(addr)
MsgBox(service1.GetData(112))
'Dim result As Variant
'result = service1.GetString
End Sub
End Module
Thank you in advance
I am trying to extend an existing ASP.NET application with a WCF service. The service must require authentication via the same Membership Provider that the rest of the site uses.
Here's the web.config file:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
<authentication mode="Forms">
<forms name=".MyAppAuthentication" timeout="5760" slidingExpiration="true" />
</authentication>
<roleManager enabled="true" defaultProvider="AspNetSqlRoleProvider">
<providers>
<clear />
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="UsersContext" applicationName="MyApp" />
</providers>
</roleManager>
<membership defaultProvider="AspNetSqlMembershipProvider">
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="UsersContext" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="10" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="MyApp"/>
</providers>
</membership>
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<bindings>
<wsHttpBinding>
<binding name="MembershipBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MembershipBehaviour">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceAuthorization roleProviderName="AspNetSqlRoleProvider" principalPermissionMode="UseAspNetRoles" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="AspNetSqlMembershipProvider" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="ServiceTestBackend.Services.TestService" behaviorConfiguration="MembershipBehaviour">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="MembershipBinding" contract="ServiceTestBackend.Services.ITestService" />
</service>
</services>
</system.serviceModel>
<connectionStrings>
<add name="UsersContext" connectionString="data source=.;initial catalog=MyApp.Accounts;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
The code of the service is very simple:
public class TestService : ITestService
{
public string FindUser()
{
var user = Membership.GetUser();
return user.UserName;
}
}
And the client is just about as simple
var client = new TestService.TestServiceClient();
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
var acc = client.FindUser();
The server is invoked, but the method fails because Membership.GetUser() returns null.
Am I missing anything in the configuration?
Try code like this :
public string FindUser()
{
if (ServiceSecurityContext.Current != null)
return ServiceSecurityContext.Current.PrimaryIdentity.Name;
return null;
}
You may as well get user name from :
IPrincipal principal = Thread.CurrentPrincipal;
String user = principal.Identity.Name
And last if you really want to get name from HttContext.Current.User or Membership.GetUser() - because you ve got much existing code - you may write Custom Module for Authentication :
Look at my post : https://stackoverflow.com/a/33523683/5295797
And read carefully section Implementation of the module.
There is also the full project that can be downloaded from a link in that post.
Regards
I think there is some confusion here. I am not sure what you want to do exactly. You can make this really simple by doing this.
public class TestService : ITestService
{
public string FindUser(string userName, string password)
{
var user = Membership.GetUser(username, password);
return (user!=null?user.userName: string.Empty);
}
}
Your client should look like;
using(var client = new TestService.TestServiceClient())
{
var response = client.FindUser(username, password);
//validate the response
}
I have a WCF service hosted inside a Windows Service. (SO its not hosted in IIS, it is selfhosted)
The application makes it possible to receive measurements through HTTP. These are currently being written to a txt file.
I also have a Task configured that runs everyday at a specific time.
The problem i have is that when i dont receive a measurement through HTTP for atleast 5 minutes the service seems to go idle.
I noticed that after 5 minutes it takes 30 seconds for the service to respond. After 30 seconds if i send measurements through http i get a fast response.
What could be the problem?
app.config
<?xml version="1.0"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false"/>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="Applicatie.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<connectionStrings>
</connectionStrings>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="LargeWeb" maxBufferSize="1500000" maxBufferPoolSize="1500000"
maxReceivedMessageSize="2000000000" transferMode="Streamed">
<readerQuotas maxDepth="32" maxStringContentLength="656000" maxArrayLength="656000"
maxBytesPerRead="656000" maxNameTableCharCount="656000" />
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="Applicatie.Applicatie" behaviorConfiguration="Proxy">
<host>
<baseAddresses>
<add baseAddress="http://localhost:5001/Applicatie"/>
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" bindingConfiguration="LargeWeb" behaviorConfiguration="webBehavior" contract="Applicatie.IApplicatie"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp/>
<CorsSupport />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Proxy">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="CorsSupport" type="WebHttpCors.CorsSupportBehaviorElement, WebHttpCors, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"/>
<!--<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>-->
</entityFramework>
</configuration>
It seems like the issue we also had. we have many self hosted services. If for some time (~1 min) service receives no requests it becomes idle, and next call is really slow.
So the reasons and solution described here
I also confirm this fix helped in our case.
Quote from there:
I have confirmed with our developers that this is a known issue. The cause is indeed related to ThreadPool and thread timeout.
One possible workaround is call ThreadPool.UnsafeQueueNativeOverlapped method in short time interval to keep thread available.
class Program
{
static void Main(string[] args)
{
using (var host = new ServiceHost(typeof(Service1)))
{
ThreadPool.QueueUserWorkItem(
new WaitCallback(delegate
{
while (true)
{
Thread.Sleep(TimeSpan.FromSeconds(100));
QueueDummyIOCPWork();
}
}));
host.Open();
Console.WriteLine("Service running...");
Console.ReadKey(false);
}
}
private static unsafe void QueueDummyIOCPWork()
{
Overlapped ovl = new Overlapped();
NativeOverlapped* pOvl = null;
pOvl = ovl.Pack((a, b, c) => { Overlapped.Unpack(pOvl); Overlapped.Free(pOvl); }, null);
ThreadPool.UnsafeQueueNativeOverlapped(pOvl);
}
}
Ok, so..
I have a WCF service that throws a WebFaultException<Error>(Error, HttpStatusCode.BadRequest) where Error is my custom, serializable object.
This all works as expected when I host the service on my local machine, and on GoDaddy's (as seen here: link removed).
But when hosted with Arvixe all I receive is a 'Bad Request' response (as seen here: link removed)
Analyzing the response headers, it appears that my local machine, GoDaddy, and Arvixe are all using the same .NET version. However, my local machine is running IIS 8.0, GoDaddy is running IIS 7.0, and Arvixe is running IIS 8.5.
So, what's causing the discrepancy? Does IIS 8.5 handle WebFaultException's differently? Nothing I find on the internet suggests it does. Or does IIS need to be configured to return WebFaultExceptions? Again, everything I read says it is configured entirely in the ASP Web.config.
Any other suggestions?
** EDIT **
I'm fairly certain this has to do with IIS and not my code, considering it works fine on my local machine (IIS8) and GoDaddy (IIS7), but not on Arvixe (IIS8.5)
Anyways, here's some snippets:
The error object I'm trying to return
[DataContract]
public class Error {
[DataMember]
public int Code { get; set; }
[DataMember]
public string Message { get; set; }
[DataMember]
public string Display { get; set; }
[DataMember]
public List<Error> Details { get; set; }
public Error(int code, string message, List<Error> details = null, string display = null) {
this.Code = code;
this.Message = message;
this.Display = display;
this.Details = details ?? new List<Error>();
}
}
Trying to return it to the client via:
throw new WebFaultException<Error>(new Error(802, "games/asdf"), HttpStatusCode.BadRequest);
The method I am trying to throw the WebFaultException from:
[OperationContract]
[WebInvoke(
Method = "GET",
UriTemplate = "/games/{game}/scores"
)]
List<Score> GetScores(string game);
I have tried adding a [FaultContract(typeof(Error))] attribute to the method but it had no effect.
Here's the Web.config registering my service
<?xml version="1.0"?>
<configuration>
<appSettings>
</appSettings>
<connectionStrings>
<!-- DEV -->
<add name="App" connectionString="XXX" />
<add name="Log" connectionString="XXX" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
<webServices>
<protocols>
<clear />
<add name="HttpGet"/>
<add name="HttpPost" />
<add name="HttpPostLocalhost" />
</protocols>
</webServices>
<pages>
<namespaces>
<add namespace="System.Web.Optimization" />
</namespaces>
</pages>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<!--old-->
<behavior name="OldService">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<!--new-->
<behavior name="V3">
<serviceAuthorization serviceAuthorizationManagerType="ScoresWs.V3.Auth, ScoresWs"/>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="REST">
<!--faultExceptionEnabled needs to be false or else we return .net exceptions as xml instead of our custom WebFaultException-->
<webHttp
helpEnabled="true"
faultExceptionEnabled="false"
automaticFormatSelectionEnabled="false"
defaultOutgoingResponseFormat="Json" />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="defaultBinding" maxReceivedMessageSize="2097152">
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="ScoresWs.WebServiceV2" behaviorConfiguration="OldService">
<endpoint
address=""
binding="webHttpBinding"
behaviorConfiguration="REST"
bindingConfiguration="defaultBinding"
contract="ScoresWs.IWebServiceV2" />
</service>
<service name="ScoresWs.V3.Api" behaviorConfiguration="V3">
<endpoint
address=""
binding="webHttpBinding"
behaviorConfiguration="REST"
bindingConfiguration="defaultBinding"
contract="ScoresWs.V3.IApi"/>
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<directoryBrowse enabled="false" />
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="WebGrease" publicKeyToken="31ad335" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
Annnnnnd lastly I activate the webservices in my Global.asax:
public class Global : System.Web.HttpApplication {
protected void Application_Start(object sender, EventArgs e) {
RouteTable.Routes.Add(new ServiceRoute("api/v2", new WebServiceHostFactory(), typeof(ScoresWs.WebServiceV2)));
RouteTable.Routes.Add(new ServiceRoute("api/v3", new WebServiceHostFactory(), typeof(ScoresWs.V3.Api)));
}
}
Solved it! Like I suspected, it had nothing to do with my code.
In the Arvixe hosting panel I had to enabled "Show detailed ASP.NET errors in browser" (WebSites->Errors->ASP.NET). However, I'm not exactly sure what impact this has on security, since the Web.config hasn't changed and I can't see the IIS configuration.
Odd that the Arvixe support team wouldn't have directed me here immediately considering 'my detailed ASP.NET errors' weren't being sent to the client.
I am fairly new to WCF. I have created a WCF RestFul service which internally has a call to google geocoding api service and a database call. As the number of concurrent users are increased, there is a drastic increase in the average response time. I am using SoapUI for performance testing. Below is a table for the variation in average response time. Could someone please advise on what might be going wrong and what all things I need to consider to get Response time < 5 sec for upto 100 threads. Thanks in advance.
(No. of Threads/Sec) (Response Time in msec Run 1) (Response Time in msec Run 2) (Response Time in msec Run 3)
1 user 1490 517 585
2 users 2264.5 785.5 853.5
3 users 1341.33 1124 1093.33
4 users 2479.75 1400.25 1317
5 users 2348.6 1432.4 1673.4
8 users 4818.25 2130.25 4726.3
10 users 7510.8 8518.2 7655.4
15 users 11869.26 12933.93 10592.2
20 users 13510.4 6319.75 14553.1
25 users 17695.6 17695.6 17695.6
35 users 20905.17 19823.2 21936.5
50 users 26235.25 26146.32 31645.87
100 users 38424.488 37417.6 39465
Edit:
Web.Config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="user" value="Mahesh" />
<add key="GeoCodingErrorDesc" value="GeoCodingErrorDesc." />
<add key="GeoCodingErrorCode" value="1111" />
<add key="CacheEmptyErrorDesc" value="CacheEmptyErrorDesc." />
<add key="CacheEmptyErrorCode" value="2222" />
<add key="DATAValidationErrorDesc" value="Schema valiation failed for the input recieved." />
<add key="DATAValidationErrorCode" value="5555" />
<add key="GenericErrorDesc" value="GenericErrorDesc." />
<add key="GenericErrorCode" value="3333" />
<add key="GeoCodingAPIKey" value="*****" />
<add key="Geocountry" value="|country:IN" />
<add key="GeoCodingAPIUrl" value="http://maps.googleapis.com/maps/api/geocode/xml?address=" />
<add key="Connectionstring" value="Data Source = MachineName; Integrated Security=True;" />
<add key="Query" value="SELECT * FROM Table where Code IN " />
</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>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ITwoWayAsyncVoid" />
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost/ESB.ExceptionHandlingServices.WCF/ExceptionHandling.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ITwoWayAsyncVoid"
contract="ExceptionHandlingService.ExceptionHandling" name="WSHttpBinding_ITwoWayAsyncVoid">
</endpoint>
</client>
<services>
<service name="SearchRequest">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="web" contract="ISearchRequest">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Search/SearchRequest.svc" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
<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="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
My interface looks as below,
[ServiceContract]
public interface ISearchRequest
{
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, UriTemplate = "")]
Stream GetList(Stream value);
}