I read lot of articles about fact that client should close connection with client.Close()
so WCF default limit does not get exceeded Thing is, I have WCF WebGet operation which basicly just returns an image.
[ServiceContract(SessionMode = SessionMode.NotAllowed)]
[ValidationBehavior]
public interface IImagesService
{
[OperationContract(Name = "ImagesGet4")]
[WebGet(UriTemplate = "/Image/{partner}/{id}/{image}_{width}_{height}.jpg")]
Stream ImagesGet2(string partner, string id, string image, string width, string height);
}
In this situation client is browser and whatever I do with wcf configuration does not help. maxConnections,maxReceivedMessageSize,maxBytesPerRead
and lot of other parameters are maxed out and still no luck.
EDIT :
This is additional code:
ImageGet
method which is called by service:
public Stream ImagesGet(string partner, string id, string image, string width = null, string height = null)
{
WSData.EventLogs.MinimalEventSource.Log.ClientIp("");
WSData.EventLogs.MinimalEventSource.Log.ServicePath("");
WSData.EventLogs.MinimalEventSource.Log.Message( DateTime.Now + " | " + partner );
bool cache;
var images = new Images();
var stream = images.ImagesGetStream(out cache, partner, id, image, width, height);
if (cache)
{
WebOperationContext.Current.OutgoingResponse.Headers.Add("Cache-Control", "public, max-age=604800");
WebOperationContext.Current.OutgoingResponse.LastModified = DateTime.Today;
WebOperationContext.Current.OutgoingResponse.SetETag(id);
}
WebOperationContext.Current.OutgoingResponse.ContentType = "image/jpeg";
OperationContext clientContext = OperationContext.Current;
clientContext.OperationCompleted += new EventHandler(delegate (object sender, EventArgs args)
{
if (stream != null)
stream.Dispose();
});
return stream;
}
The ImagesGetStream
method which is called by the above method is :
public Stream ImagesGetStream( out bool cache, string partner, string id, string image, string width = null, string height = null, string background = null )
{
string PARTNER = partner;
cache = true;
try
{
EventLogs.MinimalEventSource.Log.Load( 10, "DatabaseCall" );
var img = ImagesDL.GetImage( PARTNER, new PrimaryKey( id ) );
EventLogs.MinimalEventSource.Log.Unload( 13 );
EventLogs.MinimalEventSource.Log.Load( 14, "GettingImageDir" );
var imagesRoot = Path.Combine( BaseConfiguration.GetDocumentsSharedDirectory( PARTNER ), img.Url );
var isWatermarked = img.Group.Contains( "WEBES" ) == false && ( partner.ToUpper() == "ZG-ADRIAGATE1" || partner.ToUpper() == "LENIO-ADRIAGATE2" || partner.ToUpper() == "LENIO" );
EventLogs.MinimalEventSource.Log.Unload( 15 );
EventLogs.MinimalEventSource.Log.Load( 16, "ImageToStream" );
var stream = new FileStream( imagesRoot, FileMode.Open, FileAccess.Read, FileShare.Read );
EventLogs.MinimalEventSource.Log.Unload( 17 );
if (!string.IsNullOrEmpty(width))
{
var isBackground = !string.IsNullOrEmpty(background);
int widthp = 0;
int heightp = 0;
int.TryParse(width, out widthp);
int.TryParse(height, out heightp);
return ResizeImage(partner, stream, new Size(widthp, heightp), isBackground, img.Guest, isWatermarked, background);
}
else if(img.Group.Contains("WEBES") == false) {
Image imgToResize = Image.FromStream(stream);
if(imgToResize.Width > imgToResize.Height && imgToResize.Width > 2048 )
return ResizeImage(partner, stream, new Size(2048, 1536), false, img.Guest, isWatermarked, background);
else if (imgToResize.Width < imgToResize.Height && imgToResize.Height > 2048)
return ResizeImage(partner, stream, new Size(1536, 2048), false, img.Guest, isWatermarked, background);
else if (imgToResize.Width == imgToResize.Height && imgToResize.Height > 2048)
return ResizeImage(partner, stream, new Size(2048, 2048), false, img.Guest, isWatermarked, background);
}
return isWatermarked ? WatermarkingImage( partner, stream, img.Guest, isWatermarked ) : stream;
}
catch ( Exception )
{
cache = false;
return new FileStream( AppPath + @"\App_Resorces\NoImage.jpg", FileMode.Open, FileAccess.Read, FileShare.Read );
}
}
This is relevant part of config:
<service name="WSTraveller.ImagesService" behaviorConfiguration="ServiceBehavior">
<endpoint address="soap" binding="basicHttpBinding" behaviorConfiguration="soapBehavior" contract="WSTraveller.IImagesService" bindingConfiguration="soapBinding" bindingName="soapBinding" bindingNamespace="http://ws.adriagate.com/TRWS/ImagesService.svc/soap"/>
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="WSTraveller.IImagesService" bindingConfiguration="webBinding" bindingName="webBinding" bindingNamespace="http://ws.adriagate.com/TRWS/ImagesService.svc/pox"/>
</service>
...
<basicHttpBinding>
<binding name="soapBinding" closeTimeout="00:10:00" openTimeout="00:10:00" sendTimeout="00:10:00" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647" messageEncoding="Text">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
<security mode="None"/>
</binding>
</basicHttpBinding>
My two cents..check if this helps you:
1) try compressing the image using gzip stream or so, in our project we had to send huge datasets across wire using wcf so we used to compress and then send it across.
2) if the database is the bottleneck then you can make the db call asynchronous and use a queue mechanism to store the results and wcf client request would try and dequeue result at a regular interval.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With