I have a very simple ServiceAuthorizationManager (perhaps the simplest) and have followed various tutorials on the web but for some reason none of my breakpoints are hit and this leads to me thinking that its not being called.
Created a WCF Service Application named it WcfTest
Kept the default classes Service1.svc, IService.cs but changed method to return a string
Added a new class that inherits from ServiceAuthorizationManager
Overridden the method CheckAccessCore()
Adjusted web.config so that it uses this manager class
Run the WCF Service Application
Assembly is called WcfTest
All classes live in root of the project no folders or anything
Invoke the method and at this point I am expecting my ServiceAuthorizationManager to be called or am I wrong here? I thought the whole purpose of it was to hit the custom ServiceAuthorizationManager on every request received?
Thanks in advance, Onam.
Any more info required let me know, will be watching this like a hawk as I am very confused when this should apparently be very simple.
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(UriTemplate = "/getIt",ResponseFormat=WebMessageFormat.Json)]
string GetIt();
}
public class Service1 : IService1
{
public string GetIt()
{
return "boo!";
}
}
public class MyServiceMan : ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
try
{
//Some stuff here breakpoint set on above line not hit
return false;
}
catch (Exception e)
{
return false;
}
}
}
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="WcfTest.Service1">
<endpoint address=""
contract="WcfTest.IService1"
binding="webHttpBinding">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="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="false"/>
<serviceAuthorization serviceAuthorizationManagerType="WcfTest.MyServiceMan,WcfTest" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Are you missing endpoint behavior?
behaviorConfiguration="WebHttpEndpointBehavior"
<endpointBehaviors>
<behavior name="WebHttpEndpointBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
I had the same problem. I resolved it by setting breakpoint in my CustomAuthorizationManager CheckAccessCore method and start debugging my WCF project in Visual Studio. Then I run from my desktop WCF Client App and execute some method and it's done.
Related
I want to build a WCF service that will return a JsonP request. I want it to return the following,
jsonpCallback({"fileNames":"IDR023.T.201705201412.png, IDR023.T.201705201418.png"});
So I created the following WCF Service
IBOM.cs
[ServiceContract]
public interface IBOM
{
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json)]
string GetData();
}
BOM.cs
public class BOM : IBOM
{
public string GetData()
{
return "jsonpCallback({\"fileNames\":\"IDR023.T.201705201412.png, IDR023.T.201705201418.png\"});";
}
}
Webconfig
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="BomService.BOM" behaviorConfiguration="ServiceBehaviour">
<!-- Service Endpoints -->
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address ="" binding="webHttpBinding" contract="BomService.IBOM" behaviorConfiguration="web">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="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="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
But I am getting back
"jsonpCallback({\"fileNames\":\"IDR023.T.201705201412.png, IDR023.T.201705201418.png\"});"
I am returning a string and trying to set it up to return what I need. Is this the best way for JSONP? or is there a better way to achieve what I need
Thanks
For anyone who is interested, I worked it out. Here is the code.
IBOM
[ServiceContract]
public interface IBOM
{
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json)]
Stream GetData();
}
BOM
public class BOM : IBOM
{
public Stream GetData()
{
string jsCode = "jsonpCallback" + "({\Test:\"" + fileNames + "\"});";
WebOperationContext.Current.OutgoingResponse.ContentType = "application/javascript";
return new MemoryStream(Encoding.UTF8.GetBytes(jsCode));
}
I'm currently hosting a few web services from within a WPF application. I also have enabled automatic help pages to simplify the service documentation. Every OperationContract is decorated with a Description attribute, containing information about the method.
However, whenever I take a look at my help pages, I realize that only methods with a return type of void will correctly display their Description attribute here. Methods returning Task or Task<t> will only say "Service at localhost:XXXXX/ServiceEndpoint".
As this pattern is used for IPC, I rely a lot on async operation contracts, so most of them will return a Task or Task<t>. Is there any way to fix this issue so the help gets displayed correctly?
namespace App
{
[ServiceContract]
public interface IMainService
{
[OperationContract]
[WebGet(UriTemplate = "visibility")]
[Description("Gets the main window visibility.")]
Task<bool> GetVisibilityAsync();
[OperationContract]
[WebInvoke(UriTemplate = "visibility", Method = "PUT")]
[Description("Sets the main window visibility.")]
Task SetVisibilityAsync(bool isVisible);
[OperationContract]
[WebInvoke(UriTemplate = "menu", Method = "PUT")]
[Description("Navigates to the main menu.")]
void NavigateToMainMenu();
[OperationContract]
[WebInvoke(UriTemplate = "shutdown", Method = "PUT")]
[Description("Requests the application to shutdown.")]
void RequestApplicationShutdown();
}
}
Here is my app.config
<system.web>
<compilation debug="false" targetFramework="4.5" />
</system.web>
<system.serviceModel>
<services>
<service name="App.MainService" behaviorConfiguration="rpcServiceBehavior">
<endpoint binding="webHttpBinding"
contract="App.IMainService"
behaviorConfiguration="webHttpBehavior"
name="RpcEndpoint"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:25565/main"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="rpcServiceBehavior" >
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
Try to debug with another browser (or in incognito mode).
Explanation:
This is because you probably added a few descriptions, checked it on your browser. Then you added more description tags and checked it again on your browser which, instead of reloading the page, opened the one in cache. Browser will open page in browser in cache instead of reloading it when the page is static.
I am learning WCF these days and probably don't know where to start. I want to create WCF REST Service, which will be accesible through HTTP requests (GET, PUT...). And at same time I want to be able to add this service as service reference or web reference and use them in the Web Application client as ordinary method. This issue is quite wide so I will by grateful for any hint or direction.
At this time, I have functional services and run them on my hosting. I can add Service Reference and Web Reference. Service reference is better for new code, as I reckognized, because it use WCF communication and thus it contains all former communication channels. When I add these references, I can use reference to GetSimpleDataService, but non of its methods. When I try to add these methods as reference, problem with metadata is noted.
WCF interface:
[ServiceContract]
public interface IGetSimpleDataService
{
[OperationContract]
[WebGet(UriTemplate = "User/{ID}")]
User GetUser(string ID);
[OperationContract]
[ScriptMethod(UseHttpGet = true)]
User GetUserByMethod(string ID);
[OperationContract]
[WebGet]
string ActivationTest();
[OperationContract]
[WebMethod]
string WebMethodTest();
}
Web.config:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2"/>
</system.web>
<system.serviceModel>
<services>
<service name="StoryHubWCFApp.TestStudentService" behaviorConfiguration="serviceBehavior">
<endpoint address=""
binding="webHttpBinding"
contract="StoryHubWCFApp.ITestStudentService"
behaviorConfiguration="web"
/>
</service>
<service name="StoryHubWCFApp.GetSimpleDataService" behaviorConfiguration="serviceBehavior">
<endpoint address=""
binding="webHttpBinding"
contract="StoryHubWCFApp.IGetSimpleDataService"
behaviorConfiguration="web"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Now I can get data via GET request, but I want to be able use service with Web/Service reference like this.:
string s = MyServices.ActivationTest();
I assume to use methods like this, which returns or takes values other than int and string I should have [DataContracts]? I understood too, I have to use [WebMethod] or [ScriptMethod], but I wasn't successful so far.
Thanks in regards for any correction.
You can so it almost as smoothly as your example shows...
Since your topic is quite broad I won't go in details just give pointers.
For your own classes, to be able to use them as parameters and/or return types. (in your case User) you have to define what and how to be serialized. You can read about that here:
https://msdn.microsoft.com/en-us/library/ms733127(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/ms733811(v=vs.110).aspx
Example:
[DataContract]
public class User
{
// This member is serialized.
[DataMember]
string FullName;
// This is not serialized because the DataMemberAttribute
// has not been applied.
private string MailingAddress;
}
Now you are able to use your class.
For calling the service:
You can add service reference: https://msdn.microsoft.com/en-us/library/bb386386.aspx (this would be a generated proxy to your service)
Or you can use ChannelFactory: https://msdn.microsoft.com/en-us/library/ms734681(v=vs.110).aspx
(with this you are in full control of the code, but might need to do more settings, i.e. endpoints.)
I'm trying to add a WCF service to my MVC project to have a general place to put my ajax methods but when i try to call its' methods simply by browsing to the url (e.g. ../Service.svc/HelloWorld) or calling it with jquery ajax I get a 404 page instead.
If i do the same thing in a webforms project, it works without any problem. What am I doing wrong here? Is this not the best practice place to keep ajax methods? Like i said: I want a general place to keep my ajax methods that might be reused from several views so i dont want to put them in the controller of the view if possible
My code:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service1:IService1
{
public string HelloWorld()
{
return "HelloWorld";
}
}
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet]
string HelloWorld();
}
My configuration:
<system.serviceModel>
<services>
<service name="WebApplication1.Service1">
<endpoint address=""
behaviorConfiguration="AJAXEndpoint"
binding="webHttpBinding"
contract="WebApplication1.IService1" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="AJAXEndpoint">
<webHttp />
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" minFreeMemoryPercentageToActivateService="1" />
</system.serviceModel>
You have to add a ServiceRoute in your Global.asax. You have a 404 simply because there are no routes for this request.
For example this could be
routes.Add(new ServiceRoute("ThePath", new WebServiceHostFactory(), typeof(YourService)));
+1 for asp.net Web Api : this is definitely the recommanded way of building a web api in asp.net, especially in an existing mvc project.
I have a simple web service. This is consumed in a website using VS 2010. I added the service reference using “Add Service Reference” option in VS 2010. It works fine. It prints the service address as http://localhost:3187/Service1.svc/MyFolder. But when I type this service address in a browser it says HTTP Error 400.
Note: When I replace the address="MyFolder" with address="" in service’s end point, http://localhost:3187/Service1.svc shows the result.
What is the correct address that I should type in the browser to get the service with “MyFolder” in address?
The page:
namespace ClientWebApp
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Service1Client myClientService = new Service1Client();
Response.Write(myClientService.Endpoint.Address);
string result = myClientService.GetData(7);
lblName.Text = result;
}
}
}
The contract:
namespace MyWCFServiceApplication
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
public class MyService : IService1
{
public string GetData(int value)
{
return string.Format("Now entered: {0}", value);
}
}
}
The configuration:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="MyWCFServiceApplication.MyService"
behaviorConfiguration="WeatherServiceBehavior">
<endpoint address="MyFolder"
binding="wsHttpBinding"
contract="MyWCFServiceApplication.IService1" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WeatherServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Please take a look at the answer to this question: WCF Endpoints & Binding Configuration Issues
Quote:
When hosting a WCF service in IIS, the base address of the service is formed using the following format:
{protocol}://{host}:{port}/{applicationName}/{svcFileName}. This is
the address you can browse to get the WCF help page and/or the
metadata (on a default configuration).
To form the actual address of the endpoint (the one your client needs
to use), the following format is used:
{serviceBaseAddress}/{endpointAddress}
In your case the {endpointAddress} is MyFolder which explains why you're able to add service reference using http://localhost:3187/Service1.svc/MyFolder address. However this is not the address where your help page and metadata info gets rendered so the fact that you get HTTP Error 400 on http://.../*.svc/MyFolder is no surprise.
try adding "?wsdl" to the end of the url you are trying with.