Creating a log for WCF operations / getting app directory - wcf

I want my WCF service to log errors / operations, etc.
I have a very simple logging class but finding the directory to create / write to is returning a null reference exception:
public static string Path()
{
return Path.GetDirectoryName
(Assembly.GetEntryAssembly().Location);
}
This works in say a console app but not WCF, perhaps there is a different convention?
Or alternatively are there any simple libraries for logging in WCF?

WCF has built-in message logging, following links should help you.
http://msdn.microsoft.com/en-us/library/ms730064.aspx
http://geekswithblogs.net/mnf/archive/2008/10/03/use-wcf-message-logging.aspx
http://mkdot.net/blogs/dejan/archive/2008/10/23/wcf-tracing-and-message-logging.aspx

Related

How to add logging to WCF?

I've used the solution from here for logging (and insert to DB) REST request successfully, now i have to do the same to WCF
[LogApiRequest]
public NadlanData GetNadlanData(decimal Id, KodFamilyEnum KodFamily)
{
ClsDalByTz objByTz = new ClsDalByTz();
return objByTz.getDataFromMF(Id, DateTime.Now.Year - 5, (decimal)KodFamily);
}
I've tried to do the same by adding [LogApiRequest] to the WCF function but it did not work.
How can i implement the same solution for WCF?
The custom attribute - LogApiRequest - derives from System.Web.Http.Filters.ActionFilterAttribute. Action filter attributes are documented here - https://www.tutorialsteacher.com/webapi/web-api-filters and here - https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/understanding-action-filters-cs.
The reason your attribute works in your web api is because asp.net or asp.net core processing pipeline supports calling custom code defined in user defined code - you are plugging custom feature in the processing pipeline.
Know more about asp.net pipeline here - https://learn.microsoft.com/en-us/archive/msdn-magazine/2002/september/asp-net-request-processing-filtering-and-content-redirection
The reason it does not work with WCF is because that processing pipeline does not support customisation through HTTP filters.
WCF has its own way of doing logging. Check out these links - https://learn.microsoft.com/en-us/dotnet/framework/wcf/diagnostics/tracing/configuring-tracing and https://learn.microsoft.com/en-us/dotnet/framework/wcf/samples/tracing-and-message-logging
You will find yourself editing custom configuration files most of the time.
I cannot give you a short attribute name or configuration script because it depends on type of WCF endpoint you are implementing, their name etc. The tracing and message logging link above contains some samples. Copy paste those configurations but edit file path and interface names based on what you have got code. That should work.

Access Business Classes in WCF methods

I have an asmx web service I am converting to WCF. In the old structure I had a number of web service methods that accessed business classes to do the work. For example:
public DataSet GetAppointmentDataToConvert(string aAccessToken, string aStartingId)
{
//verify that the user is allowed to use this web service
if (!isAuthorized(aAccessToken))
{
throw new Exception("Not authorized");
}
cls256_BitEncryptionConversion cls256 = new cls256_BitEncryptionConversion();
return cls256.GetAppointmentDataToConvert(aStartingId);
}
This method initialized the cls256_BitEncryptionConversion class and called a method inside it to do the work, then returned the result.
I am trying to set up a WCF Service that will use the cls256_BitEncryptionConversion class, but despite both the class and the service being in the same namespace, my service method is unable to "see" the class. What am I doing wrong?
These are few tips for you to resolve it your self:
Make it sure that even they have the same namespace are they in the same project?
If they are in different project add it as you reference where you want to use it. And probably add a using directive if necessary.
I was able to resolve the issue by restructuring the project. I moved all the classes from the app_code folder into the root of the project.

WCF RIA services and WSDL generation

Need help on an issue I am having. I inherited this WCF RIA project and am trying to understand a couple of things.
When I publish the project, how does the WSDL get generated and put on the URL that I published to?
And I want to incorporate FaultException handling so as to transmit the exceptions to the client side. I read some stuff regarding the FaultException on the web and was able to get a small sample working with the regular WCF service.
I thought it would be similar within my actual project. But unfortunately I am running into some issues(probably due to my lack of WCF + RIA services knowledge).
So in my actual project my Context class derives off of LinqToEntitiesDomainService.
I created a new ContextFaultException class which had some methods to capture some custom error messaging.
Then I applied the [FaultContract(typeof(ContextFaultException))] to some of the methods in my Context class. Everything compiles and all is fine. But when I published to a website and then when I added this service reference to the client, I don't see my new ContextFaultException in the Reference.cs file that's generated.
I thought may be moving it within the Context class will solve the issue. So I made my ContextFaultException class as an inner class of this Context class but I am running into some other issues. Before I try to figure out these issues, I just want to know if this the right approach?
Any suggestions/pointers??
TIA
The URL must be formatted to get to the namespace wdsl
for example:
namespace My.Namespace.Services
{
[EnableClientAccess()]
public partial class MyClassName : LinqToEntitiesDomainService<XXX>
{
....
}
}
Then use the following pattern for the url
http://YOURHOST/APP/Services/My-Namespace-Services-MyClassName.svc?wsdl
Use "-" for the "."

Calling WCF Service with no input parameters in BizTalk Orchestration

I am trying to call an IIS hosted WCF web service that simply returns the current date from a BizTalk orchestration. There are no input parameters to this service.
Please ignore the First Receive_1 and the Last Send_1 shapes as I just used them to get started with this orchestration. My Orchestration looks like:
I used the "Add Generated Items..." wizard to add the generated reference to the web service in the Orchestration. My web service definition looks like:
[ServiceContract]
public interface ICalculator
{
[OperationContract]
DateTime GetLastExecutionDate();
}
public class CalculatorService : ICalculator
{
public DateTime GetLastExecutionDate()
{
return DateTime.Now.AddMonths(-6);
}
}
After I added the generated reference to the BizTalk project, the wizard created a set of ports and Multi Part Messages like below:
I have also created local messages to transport data between these calls like below:
Now, I have read everywhere I could that I will need to construct the InputMessage in order to call a web service with no parameters.
Some forums/website say that I need to simply created a blank ConstructMessage shape with the MessageType of dateRequest Message. While doing so the project doesn't compile and I get the following error message:
And the other suggested item is to do a MessageAssignment for a blank Document. So the MessageAssginment shape in my Orchestration has the following:
xDoc = new System.Xml.XmlDocument();
xDoc.LoadXml("<GetLastExecutionDate/>");
dateRequest.parameters = xDoc;
While this compiles and get's deployed, my BizTalk instance get's suspended with the following exception:
There was a failure executing the send pipeline:
"Microsoft.BizTalk.DefaultPipelines.XMLTransmit,
Microsoft.BizTalk.DefaultPipelines, Version=3.0.1.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" Source: "XML assembler" Send Port:
"REDACTED_1.0.0.0_REDACTED.ExportData_WCFPort_dace989afd9cd9c5"
URI: "http://localhost/COMPANYNAME/WCFService/Service.svc" Reason: This
Assembler cannot retrieve a document specification using this type:
"GetLastExecutionDate".
And the parameter data passed into the service is:
So my question is: How do I call a WCF Service that does not expect any input parameters.
Go to your service request message schema file from within visual studio.
Right click -> Generate Instance.
Grab the XML instance generated and replace all the double quotes with single quotes.
Then paste this into your LoadXml() in your assignment
You probably need an XML namespace in the string used in the message assignment shape. I suggest you validate your XML string against the web service schema to make sure it makes a valid message.
You could also use xsd.exe to create .NET classes from your web service schema.
See http://msdn.microsoft.com/en-us/library/aa547985(BTS.20).aspx for a complete list of ways to contruct a message in an orchestration.
You use the XMLTransmit pipeline and there could be multiple root causes for it throwing error message
"Reason: This Assembler cannot retrieve a document specification using this type: xxx"
The most likely cause is that you do not have a schema deployed matching the message you are transmitting.
But the good news is that there is no need for the XMLTransmit pipeline in this scenario. Just change the send-pipeline to PassThruTransmit and it will most likely solve at least that problem.

Type 'System.Web.HttpRequest' cannot be serialized

I am trying to design an Picture Upload feature into a web site.
I am using ASP.NET 3.5, C#, and WCF.
I have been asked to accomplish the following:
1) Make the Uploader a Web Service
2) Return progress updates to the user as files are uploaded.
3) Log other relevant user-selected options in the database.
So, I have started off by creating a WCF web client with the
below service contract:
IService.UploadPictures(HttpRequest request);
private UploadServiceClient upload;
protected void Page_Load(object sender, EventArgs e)
{
upload = new UploadServiceClient();
upload.UploadPictures(Request.Files);
}
When I compile, I get the below error:
Type 'System.Web.HttpRequest' cannot
be serialized. Consider marking it
with the DataContractAttribute, and
marking all of its members you want
serialized with the
DataMemberAttribute attribute.
So, I went back into my service contract and
changed [OperationContract] to [DataContract]
but the change produced the same error.
Can somebody kindly tell me what I am doing wrong
and provide examples as to how to best move forward?
Thanks for your time.
You cannot use something like a HttpRequest as a WCF parameter. The error messages says it all - the HttpRequest is not serializable, and in order to work with WCF, types have to be serializable.
Also, you need to remember: you're not just passing an object instance to a method here - what you're really doing is having the WCF runtime serialize your request (the method name to call plus all the parameters passed in) into a message (think: e-mail or xml file), sending it to the server, deserialising there and building up a new copy of the given datatype (as defined in your DataContract), and doing something with it.
Your WCF service could well be self-hosted, e.g. running in a NT Service or console app - no HttpRequest available in those circumstances!
You need to definitely rearchitect your solution - you need to either check into WCF streaming to upload files to WCF (google for it - you'll find plenty of hits) or you'll need to find another way to pass the relevant info (e.g. list of filenames) to the WCF service without use of a HttpRequest object.
Marc
You are submitting a request as a parameter to a request. This is not what you want to do. I'm assuming that "Request.Files" is an array of files. This is what you want to upload. So something like:
IService.UploadPictures(List<SomeFileType> request);