WCF slow ServiceHost.Open() call - wcf

This is a similar question as this one:
Win32Exception # ServiceHost.Open() for WCF service.
I have a machine that is very slow on the ServiceHost.Open call below. It consistently takes 7 seconds or so to open the service, every time. This machine is my home box, and it is not part of a domain.
I can run the same code on another box (my work box) which is part of a domain and the service host opens in about 3-4 seconds on the first call, but if I run the program again the service host opens in about 1 second or less.
I have worked with MS support on this, and we generated trace logs and the part it's hanging in is where is goes out and tries to connect to a domain, even on the machine that isn't part of a domain. And it gets the "The specified domain either does not exist or could not be contacted." exception in the trace log, and that's where all the time is getting eaten up.
But what's really weird is that even on my work machine, if I'm not connected to a domain (like if I'm not on my work network and just running from home) I still don't get the delay.
I rebuilt my machine using Windows 7 64-bit, and the same behavior occurs (was running XP SP3, which I restored when Windows 7 didn't seem to fix the problem).
I just wondered if anyone had any ideas of what could cause this. By the way, if I disable "Client for microsoft networks", the time is like 4 seconds to open the ServiceHost, but that's still not as fast as this machine used to be able to open the service. Somehow, it thinks it's supposed to be part of a domain or something.
static void RunServiceWithinEXE()
{
Uri baseAddress = new Uri("http://localhost:11111/Demo");
ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), baseAddress);
try
{
// Add a service endpoint
serviceHost.AddServiceEndpoint(
typeof(ICalculator),
new WSHttpBinding(),
"CalculatorService");
// Enable metadata exchange
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
serviceHost.Description.Behaviors.Add(smb);
serviceHost.Opening += new EventHandler(serviceHost_Opening);
serviceHost.Opened += new EventHandler(serviceHost_Opened);
serviceHost.Open();
Console.WriteLine("The service is ready.");
// Close the ServiceHostBase to shutdown the service.
serviceHost.Close();
}
catch (CommunicationException ce)
{
Console.WriteLine("An exception occured: {0}", ce.Message);
serviceHost.Abort();
}
}
static void serviceHost_Opened(object sender, EventArgs e)
{
TimeSpan timeToOpen = DateTime.Now - shOpening;
Console.WriteLine("Time To Open: :" + timeToOpen.Seconds);
}
static void serviceHost_Opening(object sender, EventArgs e)
{
shOpening = DateTime.Now;
}
Here is my app.config, but I don't have any special security configuration settings for the service in there, only some diagnostic settings to enable the WCF trace.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<diagnostics>
<messageLogging maxMessagesToLog="30000"
logEntireMessage="true"
logMessagesAtServiceLevel="false"
logMalformedMessages="true"
logMessagesAtTransportLevel="true">
<filters>
<clear/>
</filters>
</messageLogging>
</diagnostics>
</system.serviceModel>
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Warning, ActivityTracing" propagateActivity="true" >
<listeners>
<add name="xml" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging" switchValue="Warning">
<listeners>
<add name="xml" />
</listeners>
</source>
</sources>
<sharedListeners>
<add name="xml" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\Temp\Server.svclog" />
</sharedListeners>
<trace autoflush="true" indentsize="4">
<listeners>
<remove name="Default" />
<add name="ScottsConsoleListener" type="System.Diagnostics.ConsoleTraceListener" />
<add name="ScottsTextListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="C:\Temp\DebugLog.txt" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
Note also that my service definition has SessionMode required (see below). If I take the SessionMode requirement out, I don't get the delays.
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
namespace Microsoft.ServiceModel.Samples
{
// Define a service contract.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode = SessionMode.Required)]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
double Subtract(double n1, double n2);
[OperationContract]
double Multiply(double n1, double n2);
[OperationContract]
double Divide(double n1, double n2);
[OperationContract]
string PrintName(string firstName, string lastName);
[OperationContract]
Point MakePoint(double x, double y);
}
}

Okay, my suspicion is the fact you're using a binding (WsHttpBinding) which defaults to authenticating its callers using Windows credentials unless you specifically tell it not to.
In your service hosting code, you're just instantiating a default WsHttpBinding instance - no settings in config or code to change the default security behavior, in that case.
Just for testing purposes: try to change your service hosting code to:
// Add a service endpoint
serviceHost.AddServiceEndpoint(
typeof(ICalculator),
new WSHttpBinding(SecurityMode.None), // pass in SecurityMode.None
"CalculatorService");
This will effectively cancel out all security settings, e.g. the ServiceHost should no longer even attempt to find the Windows domain to authenticate callers against.
Does that change any of your observations?

It turns out that if I disable netbios on my network connections, I don't get the delays on the ServiceHost.Open calls. I am not sure why, but this seemed to fix the problem.
What's weird is that when I did a clean install of XP, I didn't have the delays even with the Netbios enabled, so I have no idea why it happens with my existing installation (I did the clean install on this same machine, and then restored my backup from an image to run these tests).

Also try stopping the Remote Access Auto Connection Manager service. For me, the issue came down to Dns.GetHostEntry(String.Empty) and this post http://social.msdn.microsoft.com/Forums/en/vbgeneral/thread/493d1b65-9ace-41de-b269-f178d27a8a1b

It seems I had the same Problem. Long Duration of Open call caused by an exception. I googled for configuration of security Settings for Wcf Service. Found the following solution which worked for me:
Under <wsHttpBinding> element in the Web.config file place the following entry:
<security mode="None" />
The Service Reference in the Client must be updated!

Related

Remove response Server header on Azure Web App from the first redirect request to HTTPS

I’m trying to remove the response Server header from an Azure Web App ( with an ASP Net core application )
After many tries of changing the web.config and removing the header in app code using a middleware, Microsoft doesn’t give up and set the response header to Server: Microsoft-IIS/10.0 :)
The problem appears only when I’m trying to access the server on http (not https). Response code from the server is 301, and this is the only response that has the Server header.
Checking the logs I was not able to find any request to http://, and perhaps this is why I’m not able to remove header, because the request is not process in my application code.
A solution that I’m thinking is to disable the azure HTTPS only and do the redirect to https in my code (I tested and is working - server header is removed)
Is there another workaround without disabling the HTTPS only option?
Here is what I tried
Startup.cs
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
context.Response.Headers.Add("server", string.Empty)
}
app.UseHttpsRedirection();
}
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<httpRuntime enableVersionHeader="false" />
<!-- Removes ASP.NET version header. -->
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<remove name="Server" />
<remove name="X-Powered-By" />
</customHeaders>
<redirectHeaders>
<clear />
</redirectHeaders>
</httpProtocol>
<security>
<requestFiltering removeServerHeader="true" />
<!-- Removes Server header in IIS10 or later and also in Azure Web Apps -->
</security>
<rewrite>
<outboundRules>
<rule name="Change Server Header"> <!-- if you're not removing it completely -->
<match serverVariable="RESPONSE_Server" pattern=".+" />
<action type="Rewrite" value="Unknown" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
UPDATE
When the URL of http:// is requested, IIS will process it, this time without code. So we can't control it by the code, we can only set it on the server, such as some scripts or tools. But on Azure, we have no way to directly operate as a physical server, so after exploration, I suggest that Front Door can be used to deal with this problem. Hiding server information through proxy should be a better way.
After my test, the server information is hidden, you can refer to this document . We can see from the picture that there is no 301 redirect request, and no server information in other requests.
PREVIOUS
You need to modify Global.asax.cs and Web.config file in your program.
In Global.asax.cs.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
MvcHandler.DisableMvcResponseHeader = true;
PreSendRequestHeaders += Application_PreSendRequestHeaders;
}
protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
//HttpContext.Current.Response.Headers.Remove("Server");
HttpContext.Current.Response.Headers.Set("Server","N/A");
}
}
And In Web.config.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" >
</modules>
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>
</system.webServer>
Then u can deploy your app. After the above code modification, access to the interface or static resources can see that the server information is modified, of course, it can also be deleted by Remove.
You also can handle special event by http status code.
protected void Application_PreSendRequestHeaders(object sender, EventArgs e)
{
//HttpContext.Current.Response.Headers.Remove("Server");
int StatusCode= HttpContext.Current.Response.StatusCode;
// handle like http status code 301
HttpContext.Current.Response.Headers.Set("Server","N/A");
}

no configuration section <common/logging> found

I'm using system.diagnostic to log all the errors to a log file
Web.Config:
<system.diagnostics>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="MyListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="MyListenerLog.txt" />
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
Code:
private static void AddToMyListner(string message)
{
try
{
System.Diagnostics.Trace.WriteLine("Text: " +message + "," + DateTime.UtcNow);
System.Diagnostics.Trace.Close();
}
catch (Exception ex)
{
throw ex;
}
}
In the Log file the first log i got was
no configuration section <common/logging> found - suppressing logging output
This log is printed only once i.e. only when I create a new log file. I'm not using Common.Logging so i was wondering what is causing this issue.
Common.Logging is commonly integrated with tracing. If you're getting this error and you're not deliberately referencing Common.Logging then you're probably referencing some external library that uses Common.Logging and subscribes to the trace by default. If there's no configuration in place (reasonable, since you're not intending to use Common.Logging) then this would happen when Common.Logging receives a notification that something was written to the trace and doesn't know what to do about it.

WCF service not working because of return data type?

I have created a WCF service with 2 methods :
[ServiceContract(Namespace = "")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MyDataService
{
[OperationContract]
public IQueryable<object> Service1()
{
PivotData pivot = new PivotData();
IQueryable<object> list = pivot.GeneratePivotData();
return list;
}
[OperationContract]
public string Service2()
{
return "hello";
}
}
The Service2 works perfectly fine. However , service1 returns the dreaded
"the remote server has returned an error : not found"
I believe it has to do with the return type IQueryable<object> , but I don't know what I should change to make it work. I tried List<string> , ObservableCollection<object> and a few others but to no avail.
What should I do the get my data back to the client ?
Thanks
depending on the question and conversation with Aron.
I supposed it is a WCF-Ria Services If so please retag the question, otherwise you may ignore this answer.
Try the below code.
Beside if you use ria services. you should use , [Association("FK_assos_name", "field", "field")] [Include] for complex properties and your base class should have at least one [Key] attributed field. Such as ID.
[OperationContract]
public BaseClass[] ServiceMethod1()
{
PivotData pivot = new PivotData();
IQueryable<object> list = pivot.GeneratePivotData();
return list.ToArray();
}
If you still get errors trace it;In your web.config add the lines below. Then open WcfDetailTrace.svclog with svclog viewer. Red parts will show you what goes wrong.
<system.diagnostics>
<trace autoflush="true">
<listeners>
</listeners>
</trace>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="sdt"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "WcfDetailTrace.svclog" />
</listeners>
</source>
</sources>

REST WCF service returns XML response but not JSON response

I am new to WCF so I think this is pretty basic. I have a simple method that a single "order" object is returned. It works just fine when using the default XML, however, when I apply the
ResponseFormat = WebMessageFormat.Json
attribute, it fails to return JSON. The code successfully executes and hits the return line but then the method is immediately called again and then finally a third time before the browser returns an error stating the connection to localhost has been interrupted.
When I remove the ResponseFormat = WebMessageFormat.Json, the method is called and XML is returned just fine. Not sure I am missing for the JSON.
IProductSales.cs
namespace ProductsSalesService
{
[ServiceContract(Name = "ProductsSales")]
public interface IProductsSales
{
[OperationContract]
[WebGet(UriTemplate = "Orders/{orderID}", ResponseFormat = WebMessageFormat.Json)]
[Description("Returns the details of an order")]
SalesOrderHeader GetOrder(string orderID);
}
}
ProductSales
public SalesOrderHeader GetOrder(string orderID)
{
SalesOrderHeader header = null;
try
{
int id = Convert.ToInt32(orderID);
AdventureWorksEntities database = new AdventureWorksEntities();
header = (from order in database.SalesOrderHeaders
where order.SalesOrderID == id
select order).FirstOrDefault();
}
catch
{
throw new WebFaultException(HttpStatusCode.BadRequest);
}
return header;
}
I am working through an sample in a WCF book so they had me build a small console application to be the host, so this is the app.config file I have for the host client.
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="AdventureWorksEntities" connectionString="metadata=res://*/ProductsSalesModel.csdl|res://*/ProductsSalesModel.ssdl|res://*/ProductsSalesModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=BINGBONG;Initial Catalog=AdventureWorks;Integrated Security=True;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
</connectionStrings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup><system.serviceModel>
<services>
<service name="ProductsSalesService.ProductsSales">
<endpoint address="http://localhost:8000/Sales" binding="webHttpBinding"
bindingConfiguration="" name="ProductsSalesService.ProductsSales"
contract="ProductsSalesService.IProductsSales" />
</service>
</services>
</system.serviceModel>
</configuration>
Finally, this is just the host client code.
public class Program
{
static void Main(string[] args)
{
WebServiceHost host = new WebServiceHost(typeof(ProductsSalesService.ProductsSales));
host.Open();
Console.WriteLine("Service running");
Console.WriteLine("Press ENTER to stop the service");
Console.ReadLine();
host.Close();
}
}
So when I go to http://localhost:8000/Sales/Orders/43659 to pull up my order it hits three times and the page cancels in Chrome with the following error:
This webpage is not available The connection to localhost was
interrupted. Here are some suggestions: Reload this webpage later.
Check your Internet connection. Restart any router, modem, or other
network devices you may be using. Add Google Chrome as a permitted
program in your firewall's or antivirus software's settings. If it is
already a permitted program, try deleting it from the list of
permitted programs and adding it again. If you use a proxy server,
check your proxy settings or contact your network administrator to
make sure the proxy server is working. If you don't believe you should
be using a proxy server, adjust your proxy settings: Go to the wrench
menu > Settings > Show advanced settings... > Change proxy settings...
LAN Settings and deselect the "Use a proxy server for your LAN" checkbox. Error 101 (net::ERR_CONNECTION_RESET): The connection was
reset.
If I remove the WebMessageFormat.Json everything works fine!
Thanks for any assistance!
For starters try WCF tracing/logging to see if it sheds any light on things.
Put this in your server's config file (somewhere within the <configuration> element):-
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Error" propagateActivity="true">
<listeners>
<add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\Temp\server.svclog"/>
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="messages"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="C:\Temp\server_messages.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
And put this inside the <system.serviceModel> element:-
<diagnostics>
<messageLogging
logEntireMessage="true"
logMalformedMessages="false"
logMessagesAtServiceLevel="true"
logMessagesAtTransportLevel="false"
maxMessagesToLog="3000"
maxSizeOfMessageToLog="2000"/>
</diagnostics>
Try hitting your service again and examine the .svclog files that this (hopefully) generates for clues. The files will open in a "Service Trace Viewer" tool - if not it can be downloaded from MS (part of the Win SDK I think).
Although my fault is actually unrelated, this is the first article I found when looking into my problem which is that my service was failing and I was seeing an error connection has been interrupted.
My fault was to do with the fact that the class I was outputting from my WebGet method had properties that had DataContract attributes but I had not added a Set accessor to each one (because I considered them to be output-only I didn't see the point).
Adding the tracing into my configuration file quickly revealed that the fault was that there were no Set accessors, so I added private set accessors to each DataContract property and all is now working as expected.
I have added this here in case anyone else follows the same search path and has the same issue.
This line of code will construct Service Host without taking configuration into account so you will have Service but it will listen different URL.
WebServiceHost host = new WebServiceHost(typeof(ProductsSalesService.ProductsSales));
Add base address new WebServiceHost plus code below:
WebChannelFactory<ProductsSalesService.IProductsSales> cf =
new WebChannelFactory<ProductsSalesService.IProductsSales>("ProductsSalesService.ProductsSales");
ProductsSalesService.IProductsSales channel = cf.CreateChannel();
See full code here - http://msdn.microsoft.com/en-us/library/bb919583

WCF tracing & message logging - trace level warning

Assume I have a config file which looks like this:
...
<system.diagnostics>
<sources>
<source name="System.ServiceModel" switchValue="Warning,ActivityTracing" propagateActivity="true">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
<source name="System.ServiceModel.MessageLogging">
<listeners>
<add name="ServiceModelTraceListener" />
</listeners>
</source>
</sources>
<sharedListeners>
<add initializeData="LogServer.svclog" type="System.Diagnostics.XmlWriterTraceListener" name="ServiceModelTraceListener" />
</sharedListeners>
<trace autoflush="true" />
</system.diagnostics>
When using this config file every activity the caller performs against the service and each corresponding message that's sent to the service will be logged in the svclog file. Everything fine so far.
If I modify the 3rd line from the above listing to <source name="System.ServiceModel" switchValue="Warning" propagateActivity="true"> (the ActivityTracing is removed) then only those activities are logged that are at least labeled level warning. But it's still every message logged...
So is there a way to only log those message that correspond to those activities that are at least warnings? Those messages that succeeded aren't very interesting in that moment, but those messages that belong to the unsuccessful activities are!
Edit
To filter messages beyond the options below you may want to look into writing your own TraceSource.
Below is one I am using for a project. You could easily customize it to filter out the messages you want or perhaps hide activity if it is not in DEBUG, etc.
class DB : TraceSource
{
public DB(string name) : base(name)
{
}
public DB(string name, SourceLevels sourceLevels) : base (name, sourceLevels)
{
}
public void Log(object value)
{
WriteLine(value);
}
public void Error(object value)
{
WriteLine(value, TraceEventType.Error);
}
public void Error(RecordingResponseData errorResponse)
{
string errorMessage = "[Error] Code: "+errorResponse.ErrorCode +" Message: "+errorResponse.ErrorMessage;
WriteLine(errorMessage, TraceEventType.Error);
}
public void Warn(object value)
{
WriteLine(value, TraceEventType.Warning);
}
public void WriteLine(object value, TraceEventType type = TraceEventType.Information)
{
TraceEvent(type, 0, value.ToString());
}
}
Original
Your options are:
Critical
Error
Warning
Information
ActivityTracing
Verbose
All
Or a combination there of. If you have it set to Warning but are still getting too many messages then you may want to try Error or Critical.
ref: https://msdn.microsoft.com/en-us/library/ms733025%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
There's a switchValue available for the System.ServiceModel.MessageLogging trace switch as well. Just add that attribe to that source element and set it to Warning also and you will only see messages logged that are related to warnings.
Get rid of System.ServiceModel.MessageLogging source to get rid of logging messages to resolve "still every message logged".