WCF 3.5 - Remove SVC Extension - Special Case - c#

I have several RESTful endpoints like such:
System.Security.Role.svc
System.Security.User.svc
etc.
This is meant to be a namespace so our RESTful URL's would look like:
/rest/{class namespace}/{actions}
I have tried a few examples to get the SVC extension removed when my endpoint has multiple periods in it, however, nothing seems to work.
I have tested with the WCF REST Contrib package (http://wcfrestcontrib.codeplex.com/), this example (http://www.west-wind.com/weblog/posts/570695.aspx), and another StackOverflow post (How to remove the ".svc" extension in RESTful WCF service?).
This works great when my endpoint is something like this:
Echo.svc
It will properly remove the SVC extension.
Any ideas on how to handle endpoints with multiple periods in the endpoint name?
EDIT:
After some further testing, I found out that it is failing because whenever you do:
string path = HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath;
If the endpoint contains multiple periods, it strips off everything after the endpoint causing all of the standard IHttpModule's to fail.
Example:
If I call http://localhost/services/Echo/test, my relative app file path has a returned value of:
~/echo/test
However, if I make a call as http://localhost/services/System.Security.User/test, then my relative app file path has a returned value of:
~/system.security.user
I am missing the '/test' on the end in that situation.

Have you tried this solution - How to remove the ".svc" extension in RESTful WCF service?

Related

ASP.NET Core 2.1 get current web hostname and port in Startup.cs

I want to register my WebAPI to Consul service discovery and for that I should provide URL of my WebAPI (for example: http://service1.com) and health check endpoint (http://service1.com/health/check). How can I get that URL?
I found this piece of code:
var features = app.Properties["server.Features"] as FeatureCollection;
var addresses = features.Get<IServerAddressesFeature>();
var address = addresses.Addresses.First();
var uri = new Uri(address);
It returns 127.0.0.1:16478 instead of localhost:5600. I think first one used by dotnet.exe and second one is IIS which forwards 5600 to 16478. How can I get localhost:5600 in Startup.cs?
Well, there are multiple solutions for this problem. Your address is this:
string myurl = $"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}";
It returns 127.0.0.1:16478 instead of localhost:5600
You got this right yes. One is from IIS and one from dotnet. So, you have a problem of trying to get correct url. Ok, so what happens if you service is behind reverse proxy? https://en.wikipedia.org/wiki/Reverse_proxy
Then your service will not be exposed directly to internet, but requests made to specific url will be passed from reverse proxy to your service. Also, you can configure reverse proxy to forward additional headers that are specifying where the original request came from. I think that most reverse proxies are using X-Forwarded-For (Some of them are using X-Original-Host etc).
So if you have proper header set on RP, then you can get url like this:
url = url.RequestContext.HttpContext.Request.Headers["X-Forwarded-For"]
Url is of type UrlHelper. To simplify this method, you can create extension method (GetHostname(this UrlHelper url)) and then us it in your controller or wherever you want. Hope it helps
I don't think it is possible since there is usually a reverse proxy in production that handles public address and the application itself should not be exposed to public and, therefore, be aware of public address. But there can be some workarounds:
Place URL is some kind of config file that can be updated during deploy steps to have the correct URL.
Application can get full URL of the request like this, so after first actual request to the application we can get hostname.
EDIT: I reread your question. You wanted to know how to do this in Startup.cs. You can, but with fewer fallbacks. Your only choices are configuration or raw DNS.GetHostName(), which are less than ideal. Instead, upon any request to your service, lazily register your API. This is when you have context. Prior to that, your service knows nothing Jon Snow. The first request to your API is likely going to be health-checks, so that will kick off your registration with consul.
A solution I've used is a combination of configuration and headers in a fallback scenario.
Rely first on the X-Forwarded-For header. If there are cases where that doesn't apply or you have a need to... you can fallback to configuration.
This works for your use case, discovery. That said, it also works when you want to generate links for any reason, (e.g. for hypermedia for JSON API or your own REST implementation).
The fallback can be useful when there are reconfigurations occuring, and you have a dynamic configuration source that doesn't require a redeployment.
In the ASP.NET Core world, you can create a class and inject it into your controllers and services. This class would have a method that knows to try config first (to see if overriding is needed) and then the X-Forwarded-For header, and if neither is appropriate, fallback further to HttpContext.Request to get relevant URI parts.
What you're doing is enabling your API to be contextless and resiliency (to change) by giving it some contextual awareness of where "it lives".
This happens when you try to get current URL in Startup.cs. I've faced this issue before. What i did as Solution for my problem is. I Just declared Custom Setting in AppSettings in web.config(For Local) file and web.release.config(For Live)
like following
in web.config
<appSettings>
<add key="MyHost" value="http://localhost:5600" />
</appSettings>
in web.release.config
<appSettings>
<add key="MyHost" value="http://myLiveURL.com" />
</appSettings>
in startup.cs
string hostSetting = ConfigurationSettings.AppSettings["MyHost"];
And different host in release file. so what it helped is i can get Localhost URL in local website from web.config and Live URL from web.release.config.
if you are using Azure for live. it will be more easier for live(you would not need to add setting web.release.config file). add app setting in your website application setting https://learn.microsoft.com/en-us/azure/app-service/configure-common
In Case of ASP.NET Core you can use appsettings.json instead of web.config

Host WCF request at root

I have a WCF POX (RESTful) service which is working well. It can be accessed at a Url which takes the format https://APPLICATIONNAME/service.svc/postdata
The APPLICATIONNAME is the host name and DNS name, to map the call through to IIS 7.
The question I have now, is that ideally I wouldn't want to use the "service.svc" part of the url and just use the following Url to post to the application;
https://APPLICATIONNAME/postdata
Any pointers on how I do this? Ideally I wouldn't want to use aspnetcompatibility. I would have thought this would be a standard thing to do - but can't fine on tips on how to do it.
Many thanks

C# Calling Web Services to different URLs

I'm new to Web Services from C#, but have worked C# for years, just never needed to use Web Services. Due to privacy issues, I can't disclose actual URL, but there is a test server and a production server where the web services are identical in all other respects, and the services were written / managed by another entity.
https://LiveSite.SomeDomain.com/FolderInWebSite/TestWebServiceSoapHTTP
and
https://TestSite.SomeDomain.com/FolderInWebSite/TestWebServiceSoapHTTP
Do I need to create two separate web references to the project and create different instances of them to go, or can I via some property just change which URL version it is sending data to.
Additionally, not being familiar working web services, I see the classes as Visual Studio imported. I can create instances of the classes and set the applicable properties (int, dates, strings, string[] arrays, etc). But not seeing how to actually say ... Go send it now. and then getting the response back.
I've done this from an older application with another language and was doing direct with HTTP and SOAP where I was able to make my own connection to the URL, build the body of the SOAP message, then send it.
Just use the "Url" property.
var myProxy = new MyProxy();
myProxy.Url = "http://foo.com/myservice";
Edit for second part of the question:
There should be a method for each action exposed the API that you can call. For example if the API exposes a MyAction that takes a string, the code generator should have generated a method that you can use like so:
myProxy.MyAction("hello");

Accept WCF request in WebAPI

I need to enable my webAPI REST service to accept a request in the format of:
www.someURL.com/OldService.svc
I am working on an existing application that used to use WCF. These methods do not have to return anything but a 200 response. We need the REST service to handle this call so we can retire the old WCF service, but systems will fail if we don't support this WCF request.
Has anybody done this before?
edit:
Is it possible to do this with just adding a new route?
You can add a WCF service (.svc) to a Web API project by simply adding a New Item and selecting Web, it will then show up in the list as WCF Service.
Maybe you could use the Route attribute(using System.Web.Http) for the old service? I've used this for route names like [Route("SomeRoute")] but I'm not 100% sure if the .svc extension will interfere with anything.
[Route("OldService.svc")]
[HttpPost]
public HttpResponseMessage NewData(Data SomeData)
{}

The methods xx and yy use the same SOAPAction

We are trying to create a mock service for a web service for testing purposes.
To do this we run wsdl.exe to create an interface and then create an asmx web service based on that interface. We have done this several times over the last years without any problems.
This time we get an error:
The methods xx and yy use the same SOAPAction
When we call the web service. Have done some searching on google, it says that this is a bug with wsdl.exe. But says nothing about what to do about it.
Is there a way to fix this? Should I just delete parts of references.cs?
Thanks
Shiraz
Found the solution. Added the following line as an attribute to the web service class:
[SoapDocumentService(RoutingStyle=SoapServiceRoutingStyle.RequestElement)]
After a clean solution and a rebuild, everything worked.

Categories