I've created a fairly simply web service that has 1 method: UploadFile. Obviously, it works on my machine ©. However, once I upload it, the method return status 202 (Accepted). However, the file never arrives there and there are no errors that I can see. I've added logging to pretty much every second like of code, but it does not seem like the method actually executes.
How do I debug something like that?
Here is my server-side code for reference:
[ServiceContract]
interface IUploaderService
{
[OperationContract(IsOneWay = true)]
[WebInvoke(Method = "POST", UriTemplate = "/UploadFile?fileName={fileName}")]
void UploadFile(string fileName, Stream fileContents);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class UploaderService : IUploaderService //ServiceHostFactory
{
public void UploadFile(string fileName, Stream fileContents)
{
Log.Add("In UploadFile");
}
}
You have an interesting problem, and I played around with it and wrote a solution in the post at http://blogs.msdn.com/b/carlosfigueira/archive/2011/08/02/wcf-extensibility-system-diagnostic-tracing.aspx.
Basically, instead of tracing to a file (which is the usual way of doing tracing), you'd add a custom trace listener which would collect the traces from your application. You can use one of the databases provided by GoDaddy (MySql, SqlServer, EasyDB), or like in the code sample linked in the post, store the traces in memory and expose them via another WCF service.
try following
[ServiceContract]
interface IUploaderService
{
[OperationContract(IsOneWay = true)]
[WebInvoke(Method = "POST", UriTemplate = "/UploadFile?fileName={fileName}")]
[WebContentType("application/octet-stream")]
void UploadFile(string fileName, Stream fileContents);
}
If it doesn't work I would also try
[OperationContract]
this way if something happens on service you will have feedback on client side.
Related
I have various interfaces (endpoints) in a WCF service host, each for a completely different concern. In a classic soapy web service, I'm able to define a base host address (e.g. http://myhost.com/) and map each interface to a relative URI (IServiceContract -> service/, IMaintenanceContract -> maintenance/) so I can call them by e.g. http://myhost.com/service/mymethod.
Now I'm taking my first steps towards a RESTful WCF service using JSON as message format for CRUD web requests and the only thing I see to address an operation is by using the UriTemplate field from WebInvoke (or WebGet) attribute. Unfortunately, it doesn't seem that I can put this on the interface, just on operation contract methods.
How can I map each interface to a different relative URI?
Yes, you'll put the base url on the [OperationContract] methods. This is OK though, because you can specify any base url you want. Here is a sample interface that gives you this control.
namespace MyHostApi
{
[ServiceContract]
public interface IMyHostApi
{
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "WhateverYouWant/HelloWorld/{name}")]
string HelloWorld(string format, string name);
}
}
I have hosted a Rest WCF to my IIS 7. I tested the everything and it works fine except to importing the dll. My instance class code are following:
[OperationContract, WebInvoke(Method = "GET", UriTemplate = "/getname?name={name}&age={age}", ResponseFormat = WebMessageFormat.Json)]
bool getname(string name, string age);
[OperationContract, WebInvoke(Method = "GET", UriTemplate = "/getcallfromdll?name={name}&age={age}", ResponseFormat = WebMessageFormat.Json)]
bool getcallfromdll(string name, string age);
Whereas the definition of above methods are :
public string getname(string name, int len)
{
return "It's working";
}
public string getcallfromdll(string name, int len)
{
return UnsafeNativeMethods.getvalue(name, len); //Unsafe.. is a internal structure
}
internal static class UnsafeNativeMethods
{
const string _dllLocation = "school.dll";
[DllImport(_dllLocation, CallingConvention = CallingConvention.Cdecl)]
public static extern bool getvalue(string name, String len);
}
When tried to run localhost:8085/service.svc/getname?name=kajn&len=21: it returns "It's working", which is correct but whenever i tried to call localhost:8085/service.svc/getcallfromdll?name=kajn&len=21: It returns The server encountered an error processing the request. See server logs for more details.
I searched for it and somehow i got to know that it all happening due to service are not bale to find the DLL. To solve this i tried to put my dll in following places but it didn't help me:( :
system32/inetsrv
SysWOW64/inetsrv
in bin folder
i also put the same folder where the project exists.
But nothing works for me. Please suggest me a solution.
NOTE: there are no problem with the dll because i call the dll methods from a self hosted WCF application and it was working perfectly. At that time i put my dll into bin/debug folder.
I would guess that it could be related to the fact that IIS may copy binaries to shadow location and when it does that it may not realize the unmanaged dll may be required. Is your "school.dll" part of your WCF solution and is it added as an reference? Also does it depend on any other unmanaged dlls? Next time you get that error you can try to search your system to find all instances of your WCF dll, then if you find one in shadow location, take a look if your "school.dll" is there too.
Well, you should turn on WCF Tracing on the server and see what the actual error/exception is. But I would suspect some sort of permissions-related error... i.e. the DLL can be found, but the IIS worker process doesn't have the right permissions to read it or to execute methods in it. Just for debugging purposes, try setting the permission on the DLL such that it can be read/executed by "Everyone".
I have WCF Web service using https. It has next interface:
[ServiceContract]
class Service
{
[OperationContract]
[WebInvoke(UriTemplate="Method", BodyStyle=WebMessageBodyStyle.Bare)]
byte[] Method(Stream request)
{
// ... Some logic ...
return someBytes;
}
}
This works good but has one little issue. After method completition it closes up https connection. I have another method in service with WebGet. It returns Stream object, and this one doesn't close https connection.
I've tried to use same approach in my first Method and rewrited it as follows:
[ServiceContract]
class Service
{
[OperationContract]
[WebInvoke(UriTemplate="Method", BodyStyle=WebMessageBodyStyle.Bare)]
Stream Method(Stream request)
{
// ... Some logic ...
return new MemoryStream(someBytes);
}
}
But when I'm trying to consume Method with a client the service responds: "Method not allowed. Allowed: GET, HEAD".
Please tell me if I'm doiing it wrong by returning Stream object, or I have missed something.
UPD:
I also appreciate in any hints about tracing down this problem.
I've written a C# Windows Service that provides a REST api through WCF. This Service needs to call another web service which also uses a REST api. My service can communicate perfectly with the other service unless someone has made a call my service and it is currently responding. I wrote up a simple test:
public void TestConnection()
{
WebChannelFactory<IOtherService> wf = new WebChannelFactory<IOtherService>(otherURI);
IOtherService service = wf.CreateChannel();
service.Test();
}
[ServiceContract]
public interface IOtherService
{
[WebGet(UriTemplate = "services/account?username=testuser&password=d625a4de623dce36af2b75102eaf0ce7&locale=en-US", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
[OperationContract]
AccountServiceInfo Test();
}
Normally when I call TestConnection it works perfectly, but when someone makes a call to my service that requires me to call TestConnection the other service sees a POST rather than a GET and returns 400. Does anyone have any idea why this might be the case or how I can fix it? Thanks.
When using a WebChannelFactory inside a WCF service that already has an OperationContext, you may need to create a new context before being able to successfully callout using a channel created by the WebChannelFactory.
public void TestConnection()
{
var wf = new WebChannelFactory<IOtherService>(otherURI);
var service = wf.CreateChannel();
using ((IDisposable)service)
using (new OperationContextScope((IContextChannel)service))
{
service.Test();
}
}
http://blogs.msdn.com/b/pedram/archive/2008/07/19/webchannelfactory-inside-a-wcf-service.aspx
Problem is I have a very simple WCF REST service, which I wrote starting from the WCF Service application template.
I have one method, one class set up like this
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class MainService
{
[WebGet(UriTemplate = "{ricCode}")]
public IdentifierInfo GetByRicCode(string ricCode)
{
...
}
}
When ran from my machine I have no problems it works fine (typical).
My problem is that when I publish this to a website on IIS6 (set up for anonymous access and on a virtual server) all I get from the above method is a 400 - invalid request.
When I changed the method as a test to this
[WebGet(UriTemplate = "")]
public string GetByRicCode()
{
return "foo";
}
and ran in on the IIS6 server it worked fine.
Maybe I set up the virtual server wrong on IIS... any ideas please?
I figured out the problem, it was throwing an exception due to nested web.configs
How annoying.