WCF service relative uri without .svc - c#

I have a solution with 3 projects:
MEProject.WCF.ServiceLayer (Service-Implementation)
MEProject.WCF.HostConsole (Console Application which can host the service)
MEProject.WCF.HostIIS (WCF Service Application)
My goal is that I can switch between the 2 projects without changing the uri (the endpoint configurations) in the client project. Well, the problem is, if I start the console application, the endpoints are
http://localhost:8080/MultipleEndpointService/FirstEndpoint
http://localhost:8080/MultipleEndpointService/SecondEndpoint
But if I start the WCF service application, the endpoints are
http://localhost:8080/MultipleEndpointService.svc/FirstEndpoint
http://localhost:8080/MultipleEndpointService.svc/SecondEndpoint
As you can see, the difference is the ".svc". Now my question: How can I tell the WCF service application to act like the console application and not to have the ".svc" in the uri?
Here is the code I use to get the multiple endpoints in the console application:
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
serviceHostBase.ChannelDispatchers.ToList().ForEach(channelDispatcher =>
{
ChannelDispatcher dispatcher = channelDispatcher as ChannelDispatcher;
if (dispatcher != null)
{
dispatcher.Endpoints.ToList().ForEach(endpoint =>
{
endpoint.DispatchRuntime.InstanceProvider = new CallBackInstanceProvider(serviceDescription.ServiceType, InstanceCreator);
});
}
});
}
And here is the WCF service application web.config:
<system.serviceModel>
<services>
<service name="MEProject.Service.WCF.HostIIS.MultipleEndpointService">
<endpoint name="FirstEndpoint" address="FirstEndpoint" binding="basicHttpBinding" contract="MEProject.Service.WCF.ServiceLayer.IFirstEndpoint"/>
<endpoint name="SecondEndpoint" address="SecondEndpoint" binding="basicHttpBinding" contract="MEProject.Service.WCF.ServiceLayer.ISecondEndpoint"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/MultipleEndpointService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Thanks in advance for your response!

for running a WCF without the SVC extension you will need to use routing
for example i have a service named MultipleEndpointService.svc and i want to get the service like the following:
.../MultipleEndpointService/FirstEndpoint
we can do it like this:
Global.asax:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute("MultipleEndpointService/FirstEndpoint", new ServiceHostFactory(), typeof(MultipleEndpointService)));
}
}
MultipleEndpointService.svc.cs:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MultipleEndpointService : IMultipleEndpointService
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
Web.config (for IIS7):
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</modules>
<handlers>
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd"/>
</handlers>
<directoryBrowse enabled="true"/>
</system.webServer>
source

Try URL ReWriting :
<system.webServer>
<!-- Other stuff here -->
<rewrite>
<rules>
<!-- Rewrite requests to /MultipleEndpointService.svc to /MultipleEndpointService -->
<rule name="MultipleEndpointService" stopProcessing="true">
<match url="MultipleEndpointService.svc(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
</conditions>
<action type="Rewrite" url="/MultipleEndpointService{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>

Related

WCF Service fails to receive soap requests because of xml declaration

I have programmed an WCF Service which acts as an Event Receicer in C#. A Client sending following Soap Request to the Event Receiver:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:sila="http://sila.coop" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<ResponseEvent xmlns="http://sila.coop">
<requestId>10</requestId>
<returnValue>
<returnCode>3</returnCode>
<message>command 'Reset' completed successfully</message>
<duration>PT0S</duration>
<deviceClass>8</deviceClass>
</returnValue>
<responseData><?xml version="1.0" encoding="utf-8"?><ResponseData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sila.coop//schemata/ResponseType_1.2.xsd"></ResponseData></responseData>
</ResponseEvent>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
This one is rejected and in the Service Trace Viewer I can see that there was an exception throwed:
System.ServiceModel.ProtocolException, System.Xml.XmlException,
system.xml.xmlexception data at the root level is invalid. line 1 position 1
When I start the WCF Test client, I could send a request, which looks the following:
<s:Envelope
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<ResponseEvent
xmlns="http://sila.coop"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<requestId>1</requestId>
<returnValue>
<returnCode>3</returnCode>
<deviceClass>0</deviceClass>
</returnValue>
</ResponseEvent>
</s:Body>
</s:Envelope>
This one is working, it will go through the service.
Unfortunatley I'm not able to change the client. So how could I configure or change my Service, that it understands the topmost Request with the xml declaration?
I generated the code for the event receiver via the svcutil tool from an existing mock serivce in SoapUi:
Interface:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://sila.coop", ConfigurationName="EventReceiverSoap")]
public interface EventReceiverSoap
{
[System.ServiceModel.OperationContractAttribute(Action="http://sila.coop/ResponseEvent", ReplyAction="*")]
ResponseEventResponse ResponseEvent(ResponseEventRequest request);
}
My web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.diagnostics>
<trace autoflush="true" />
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="sdt"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData= "EventReceiverSoap.e2e" />
</listeners>
</source>
</sources>
</system.diagnostics>
<system.web>
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1"/>
</system.web>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="EventReceiverSoap" />
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- Legen Sie die Werte unten vor der Bereitstellung auf "false" fest, um die Veröffentlichung von Metadateninformationen zu vermeiden. -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" externalMetadataLocation="../wsdl/ls.wsdl" />/>
<!-- Damit in Fehlern Ausnahmedetails zum Debuggen angezeigt werden, legen Sie den Wert unten auf "true" fest. Legen Sie ihn vor der Bereitstellung auf "false" fest, um die Veröffentlichung von Ausnahmeinformationen zu vermeiden. -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>
Implementation:
//[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class EventReceiverSoapClient : System.ServiceModel.ClientBase<EventReceiverSoap>, EventReceiverSoap
{
public EventReceiverSoapClient()
{
}
public EventReceiverSoapClient(string endpointConfigurationName) :
base(endpointConfigurationName)
{
}
public EventReceiverSoapClient(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public EventReceiverSoapClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress)
{
}
public EventReceiverSoapClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public ResponseEventResponse ResponseEvent(ResponseEventRequest request)
{
return base.Channel.ResponseEvent(request);
}
}

400 Bad request - REST JSON c#

I've created a C# WCF project, when I'm testing it using POSTMAN or Fiddler. I've received an error: "400 Bad Request". Also I've created an C# windows project to test, it is the same result as well. Here's my WCF Project.
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "api/createpr.json")]
PRApplication AddPR(RequestData rData);
}
I'm using this code when testing.
try
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost/WEB_Service_B1/Service1.svc/api/createpr.json");
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "{\"Test\"}";
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
Is there any problem also in my Web.config?
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<authentication mode="Windows" />
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
</system.web>
<system.webServer>
<directoryBrowse enabled="true"/>
</system.webServer>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WS_B1.Service1Behavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="WS_B1.Service1" behaviorConfiguration="WS_B1.Service1Behavior">
<endpoint address="" binding="webHttpBinding" contract="WS_B1.IService1" behaviorConfiguration="web">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
</configuration>
BodyStyle = WebMessageBodyStyle.Wrapped
This means the request needs to be a full json object. Try with the following request body:
string json = "{\"rData\": {\"PropertyName\": \"Test\"}}";
Where PropertyName is a public property of RequestData class of string type.

URL Rewriting is showing 404 Error after Upgrading Framework from 2.0 to 4.0

I have just change framework of my website from 2.0 to 4.0. And I am getting error HTTP Error 404.0 - Not Found whenever I try to open URL Rewriting webpage.
It was working fine at a time of Framework 2.0, don't know what is the wrong now. I have google many things but din't get any proper solution.
Please help me to solve the problem.
My Code is as below :
http://www.theprojectjugaad.com/PlacementAssistance.html -> Not Working
http://www.theprojectjugaad.com/PlacementAssistance.aspx -> Working
Global.asax :
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
void Application_BeginRequest(object sender, EventArgs ex)
{
if (!Request.Url.Host.Equals("localhost")
&& !Request.Url.Host.ToString().Contains("www.theprojectjugaad.com")
&& Request.Url.Host.ToString().Contains("theprojectjugaad.com"))
{
string Result = string.Concat(
"http://",
Request.Url.Authority.Replace("theprojectjugaad.com", "www.theprojectjugaad.com"),
HttpContext.Current.Response.ApplyAppPathModifier(Request.Path),
Request.Url.Query);
HttpContext.Current.Response.Redirect(Result, true);
}
}
private static void RegisterRoutes()
{
System.Web.Routing.RouteTable.Routes.Add(
"PlacementAssistance", new System.Web.Routing.Route("PlacementAssistance.html",
new RouteHandler("~/PlacementAssistance.aspx")));
}
RouteHandler.cs :
public RouteHandler(string virtualPath)
{
_virtualPath = virtualPath;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
var display = BuildManager.CreateInstanceFromVirtualPath(
_virtualPath, typeof(Page)) as IDisplay;
return display;
}
string _virtualPath;
IDisplay.cs :
public interface IDisplay : IHttpHandler
{
}
web.config :
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="Session" />
<add name="Session" type="System.Web.SessionState.SessionStateModule" preCondition="" />
</modules>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="UrlRoutingHandler" />
</handlers>
<rewrite>
<rules>
<remove name="Plesk. SEO-safe redirect for http://www.theprojectjugaad.com" />
<rule name="Plesk. SEO-safe redirect for http://www.theprojectjugaad.com" enabled="false" patternSyntax="Wildcard" stopProcessing="true">
<match url="*" />
<conditions>
<add input="{HTTP_HOST}" pattern="www.theprojectjugaad.com" />
<add input="{HTTPS}" pattern="OFF" />
</conditions>
<serverVariables />
<action type="Redirect" url="http://theprojectjugaad.com/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
What is the URL that is not working?
What I see is you've corrected the URL from .html to .aspx and it works.

Calling a local WCF service via Scriptish or Greasemonkey

I'm trying to expose a local WCF service that checks to see if a file exists in my database that can be accessed from a Scriptish script.
Is it possible to call a local URL from Scriptish or Greasemonkey (GET or POST)? I've created a WCF service hosted in IIS on my local machine, and the service is working fine. However, when I try to call the service from Scriptish the Network tab in Chrome/Firefox just says the following:
Request URL: http://localhost/service/service.svc/MatchPartial
Request Method: OPTIONS
Status code: 405 Method Not Allowed
Here is my ajax call:
$.ajax({
url: 'http://localhost/service/service.svc/MatchPartial',
type: 'POST',
contentType: 'application/json; charset=UTF-8',
dataType: 'json',
processData: true,
data: '{ "partialFilename": "testing" }',
success: function (result) {
console.log(result);
}
});
My method is decorated with:
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
public int MatchPartial(string partialFilename)
{
...
}
I have the following above my service class:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
I've tried adding the following to my service with no luck:
[WebInvoke(Method = "OPTIONS", UriTemplate = "*")]
public void GetOptions()
{
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Content-Type");
}
I feel like I've tried everything. Any help would be appreciated!
I figured out how to do it via a GET request thanks to M.Babcock for pushing me in that direction (unimportant parts intentionally left out to save space).
Service.svc:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Service : IService
{
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public bool MatchPartial(string partialFilename)
{
...
}
}
Web.config:
<configuration>
...
...
<system.web>
<compilation debug="true"
targetFramework="4.5" />
<httpRuntime targetFramework="4.5" />
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<!-- IMPORTANT FOR THIS TO WORK USING JQUERY GET OR AJAX -->
<add name="Access-Control-Allow-Origin"
value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
<system.serviceModel>
<services>
<service name="MyNamespace.Services.WCF.Service">
<endpoint address=""
binding="webHttpBinding"
bindingConfiguration=""
contract="MyNamespace.Core.Interfaces.IService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost/Service" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" />
<!-- For Debugging --->
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
</configuration>
Here's how to do it in Scriptish:
var service = "http://localhost/service/service.svc";
GM_xmlhttpRequest({
method: "GET",
url: service + "/MatchPartial?partialFilename=" + filename,
headers: { "Accept": "application/json" },
onload: function (result) {
if (result != null && result.status == 200 && result.responseJSON == true) {
videoFrame.remove();
}
},
onerror: function (res) {
GM_log("Error!");
}
});
Plain ol' jQuery:
$.get("service", { partialFilename: filename }, function (result) {
if (result == true) {
videoFrame.remove();
}
});

Why WCF service is not getting called in AJAX auto complete extender?

I am trying to consume a wcf service in auto complete extender but it is not getting called but the same thing i tried in web services it's working fine there.
Below is my sample code
In App_Code/AutoCompleteWCF.cs
[ServiceContract]
public interface IAutoCompleteWCF
{
[OperationContract]
[System.ServiceModel.Web.WebInvoke(Method = "POST",ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json)]
string[] GetCompletionList(string prefixText, int count );
}
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class AutoCompleteWCF : IAutoCompleteWCF
{
[OperationContract]
[System.ServiceModel.Web.WebInvoke(Method = "POST", ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Json)]
public string[] GetCompletionList(string prefixText, int count)
{
string[] str = new string[5];
str[0] = prefixText + "A";
str[1] = prefixText + "B";
str[2] = prefixText + "C";
str[3] = prefixText + "D";
str[4] = prefixText + "E";
return str;
}
}
AutoCompleteWCF.svc
<%# ServiceHost Language="C#"Debug="true" Service="AutoCompleteWCF" CodeBehind="~/App_Code/AutoCompleteWCF.cs" %>
Web.confifg
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5">
<assemblies>
<add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
<add assembly="System.Web.Extensions.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
<httpRuntime targetFramework="4.5"/>
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="ServiceAspNetAjaxBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="AutoComplete" behaviorConfiguration="ServiceBehavior">
<endpoint address="F" binding="webHttpBinding" contract="IAutoCompleteWCF" behaviorConfiguration="ServiceAspNetAjaxBehavior">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
</system.serviceModel>
</configuration>
WebForm1.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="AutoCompleteDemo.WebForm1" %>
<%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ccl" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<ccl:ToolkitScriptManager ID="ScriptManager1" runat="server"></ccl:ToolkitScriptManager>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<ccl:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server"
BehaviorID="AutoCompleteEx"
TargetControlID="TextBox1"
ServicePath="AutoCompleteWCF.svc"
ServiceMethod="GetCompletionList"
MinimumPrefixLength="2"
CompletionInterval="1000"
EnableCaching="false">
</ccl:AutoCompleteExtender>
</div>
</form>
</body>
</html>

Categories