We have built a WCF service for our customers and deployed the dlls. Everything works perfectly, but we have been told we have to change the URL of the WCF.
Lets say, our current WCF URL is like below
https://xxx.xxxxx.xxx/EGov/PostBox.svc
Now, they want us to change that URL to
https://xxx.xxxxx.xxx/EGov/TransferService.svc
It is easy to change the file name from PostBox.svc to TransferService.svc but we have do it for our 100 customers and that is impossible. So, we are wondering if we can do URL-REWRITE from CONFIG files.
If we can do the URL-REWRITE from config files, then we will email the config files to each customer to put it into the right folder.
I hope I made my question clear.
URL rewriting in WCF
Create a new WCF service application.
Add Global.asax file.
In Application_Start method add below lines:
RouteTable.Routes.Add(new ServiceRoute("api/Service1", new WebServiceHostFactory(), typeof(Service1)));
Add WebInvoke in Operation Contract of Service Contract (interface IService1).
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/GetData?value={value}")]
Build and browse Project.
Check this : http://gunaatita.com/Blog/URL-rewriting-in-WCF/1052
No sure whether this will help you but i had some similar scenario where i have to rewrite the URL(for me i didn't have to show .svc file name to users.
public class Route : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += delegate
{
//URL Rewriting
//---To remove the .svc extension service file name from URL----
HttpContext cxt = HttpContext.Current;
string path = cxt.Request.AppRelativeCurrentExecutionFilePath;
{
cxt.RewritePath(path.Insert(1, "/ReportingService.svc"), false);
}
};
}
}
Hopefully this will help you at least in some way
Related
Summary: I want to have an wehook url with a specific name for the webhook, rather than .../custom/ or .../genericjson/ if using those nuget packages.
i.e.
https://localhost:44300/api/webhooks/incoming/MyWebhook?code=1234567890
All the guides and the likes that I've found are either for existing Webhook nuget packages (Github, bitbucket, slack etc.) or the Generic and Custom one (that I don't really understand the difference of, besides the names, but thats another matter).
I got the genericjson one up and running and it's doing what it is supposed to, but I would much rather have a more correct url and/or name for the Webhook.
So how do I get (which I assume is what I need to get it working as I want)
config.InitializeReceiveGenericJsonWebHooks();
to instead work as if it were
config.InitializeReceiveMyWebhookWebHooks();
and thus my server listening for webhooks on the above URL (provided I add the key in appSettings and so on).
I tried looking at the definition of InitializeReceiveGenericJsonWebHooks() and InitializeReceiveGitHubWebHooks(), but there is barely any code there nor do I know how/what/where to create my own version of it.
I'm quite new to Asp.net (have previously mostly coded sites in html/css/php/javascript on Apache, rather than Asp.net/C# on IIS) so I recon there ought to be some easy way to solve it, but after an entire day searching and trying I'm at an end as to what to try next.
Edit:
Currently this is what my code (related to Webhook) looks like. Nothing special, just bare minimum to get the webhook working.
Web.config
<appSettings>
<add key="MS_WebHookReceiverSecret_GenericJson" value="1234567890123456789012345678901234567890"/>
</appSettings>
WebApiConfig.cs
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
//The revelant part to the question
config.InitializeReceiveGenericJsonWebHooks();
}
}
GenericJsonWebHookHandler.cs
namespace Project.API.Webhooks
{
public class GenericJsonWebHookHandler : WebHookHandler
{
public GenericJsonWebHookHandler()
{
this.Receiver = "genericjson";
}
public override Task ExecuteAsync(string receiver, WebHookHandlerContext context)
{
// Get JSON from WebHook
JObject data = context.GetDataOrDefault<JObject>();
//Do something with webhook
return Task.FromResult(true);
}
}
}
I finally managed to solve it.
By looking at the GitHub of AspNetWebHooks and further in to the GenericJSON WebHook that I'm using, I finally found out what was missing.
The only thing needed was create a file called HttpConfigurationExtensions.cs and copy+paste the code from the HttpConfigurationExtensions.cs source into the newely created file and change
public static void InitializeReceiveGenericJsonWebHooks(this HttpConfiguration config)
to what I wanted it to listen to
public static void InitializeReceiveMyWebhookWebHooks(this HttpConfiguration config)
like so.
Then I also needed to create a file called MyWebhookReceiver.cs and copy+paste the code from GenericJsonWebHookReceiver.cs and change the contents slightly
public class GenericJsonWebHookReceiver : WebHookReceiver
{
internal const string RecName = "genericjson";
into
public class MyWebhookWebHookReceiver : WebHookReceiver
{
internal const string RecName = "MyWebhook";
It still acts like GenericJSON webhook (which is what I wanted) but now I can use /api/incoming/MyWebhook/whateverIWant?code=123456790 as webhook URL instead of having it look like /genericjson/MyWebhook?code=1234567890.
You still need the handler file, but in the same way the two files were slightly changed here you can do the same with the handler. Create MyWebHookHandler.cs and just copy+paste the code, changing the GenericJson to MyWebHook and it should be good to go.
Nice work! If anyone else is following this, the only couple of thingf missing is the Web.config entry
<add key="MS_WebHookReceiverSecret_GenericJson" value="i=xxx,z=xxx" />
becomes:
<add key="MS_WebHookReceiverSecret_MyWebhook" value="i=xxx,z=xxx" />
As the last section of the key name needs to match the name of the new naming convention in the last section.
And the handler itself - on the constructor:
Should be:
public MyWebhookHandler()
{
this.Receiver = GenericJsonWebHookReceiver.ReceiverName;
}
not:
public MyWebhookHandler()
{
this.Receiver = "genericjson";
}
Also - there is no benefit doing the HttpConfigurationExtensions.cs step.
You do however need to to the GenericJsonWebHookReceiver.cs step for the process to work.
I have two projects - a WCF service that provides operations on a database, and an ASP.NET project running AngularJS that acts as a client to the service.
I would like to combine these into a single project. That is, when running the service, the interface (the ASP.NET AngularJS project) should appear.
I have seen some sources saying that AspNetCompatibilityMode can be used to do something like this, but I haven't seen anywhere how to actually specify a client.
Is this the right way to go about doing this? Is there a simpler way? Thanks in advance!
It is possible. I assume you want to expose existing WCF service in your ASP.NET web forms/mvc (whatever) type of project.
Steps:
1) make sure your ASP.NET project references the assembly in which is the WCF service implementation
2) change in your ASP.NET project your global.asax to:
using System.ServiceModel.Activation; // from assembly System.ServiceModel.Web
protected void Application_Start(Object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
void RegisterRoutes(RouteCollection routes)
{
routes.Add(new ServiceRoute("Services/Angular", new WebServiceHostFactory(), typeof(WCFNamespace.AngularService)));
}
This registers calls starting with the /Service/Angular prefix to be handled by your WCF service.
3) your WCF service should look like this
[ServiceContract]
public interface IAngularService
{
[OperationContract]
[WebGet(UriTemplate = "/Hello", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
[Description("Returns hello world json object")]
HelloWorld GetHello();
}
[DataContract]
public class HelloWorld
{
[DataMember]
public string Message { get; set; }
}
Note the methods - they should be decorated with [WebGet] or [WebInvoke] methods since for Angular you want to build RESTfull wcf service. Also serialization/deserialization format is set to json.
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class AngularService : IAngularService
{
public HelloWorld GetHello()
{
return new HelloWorld { Message = "Hello from WCF. Time is: " +
DateTime.Now.ToString() };
}
}
Now you should be able to get json object if you type /Services/Angular/Hello into browser.
And finally as you've noted the WCF contract implementation (in this case class AngularService) has to be marked with attribute [AspNetCompatibilityRequirements] so the IIS can host it under ASP.NET web forms/MVC project.
Disclaimer: this is very naive implementation, in real world you probably would want to catch & log exceptions that happen in service and return them to client in form of json.
I'm trying to add the Web Api functionality to an existing ASP.NET application. This should be something simple but I'v been stuck on this for hours. I've tried a bunch of things but no luck so far.
The app has several asmx services in "/api" folder. This somehow interferes with the web api routing. Ideally, I'd like to keep the existing services in the current place since there are external references to them.
Sample service:
/Api/ApiServ.asmx - I'm able to invoke the initial screen with the method list
The problem is when I try to invoke any method on one of the services e.g. /Api/ApiServ.asmx/ServMethod - I can't invoke this and I'm getting this response: "No HTTP resource was found that matches the request URI 'http://localhost:49415/api/apiserv.asmx/ServMethod'"
Here is what I have:
Global.asax:
public class WebApiApplication : HttpApplication
{
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
//RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
Sample service:
namespace WebApiTest.Api
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
[ScriptService]
public class ApiServ : WebService
{
[WebMethod]
public string ServMethod()
{
return "Test";
}
}
}
Web Api Config:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.IgnoreRoute("asmx", "api/{resource}.asmx/{*pathInfo}");
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Strangely enough, when I use a route debbuger it actually matches the asmx ignore route but the service method is not being hit. Any help appreciated!
I didn't actually figure out a proper fix as I ran out of time I had allocated for fixing this but since the solution is temporary and will be moving the asmx services to web api controllers I decided to settle for a workaround.
This is what I did:
1) In the /Api folder I created a /Legacy subfolder and moved all asmx services there
2) In global.asax Application_BeginRequest:
private void Application_BeginRequest(object sender, EventArgs e)
{
string url = Request.Url.AbsolutePath.ToLower();
if (url.StartsWith("/api") && url.Contains(".asmx") && !url.Contains("/api/legacy/"))
{
url = Request.Url.AbsolutePath.Replace("/api/", "/api/legacy/");
Context.RewritePath(url);
}
}
Note a similar thing could be achieved in a more cultured way such as using the rewrite module but this works for me a temporary solution.
If you do have an mvc portion to your API (web api help pages will add mvc)
you will need to add the following line to your RouteConfig.cs:
routes.IgnoreRoute("{resource}.asmx/{*pathInfo}");
and that will do the trick!
I am using wsfTestClient to debug a c# wcf service program. my interface for this function has
[OperationContract]
[WebGet(UriTemplate = "AddCsv?fileLoc={fileLoc}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
void AddCsv(string fileLoc);
and the corresponding class is
public void AddCsv(string fileLoc)
{
List<Entity> listOfEntries = LoadCSV(fileLoc);
PutList(listOfEntries);
}
I have a breakpoint at the declaration of the AddCsv method and I look at the fileLoc variable and it is null. Why is this acting this way? fileLoc is a directory location.
Here is a screen shot of the wcftestclient
WCF Test Client does not work for non-SOAP endpoints (a.k.a. WCF REST services). Since you decorated your operation with [WebGet] I'm assuming this is the case for you. The issue is that non-SOAP endpoints do not expose their metadata so that tools such as WCF Test Client (or svcutil) can know how to call the service.
For more information, check the post Mixing Add Service Reference and WCF Web HTTP (a.k.a. REST) endpoint does not work.
I created a WCF self hosted web service. Here are my serviceContract and OperationContract in Instace class:
[ServiceContract]
public interface ISwiperWS
{
[OperationContract, WebInvoke(Method = "GET", UriTemplate = "/getstatus?callback={Callback}", ResponseFormat = WebMessageFormat.Json)]
String getStatus(String Callback);
}
TestWS.cs
public String getStatus()
{
return "true"
}
I am accessing the endpoint of this web service from JsonP written in GWT
String url = "https://somedomain.com:8083/getstatus";
JsonpRequestBuilder jsonp = new JsonpRequestBuilder();
jsonp.setTimeout(600);
jsonp.setCallbackParam("callback");
jsonp.send(url);
I create a setup project and installed it on different-different machine. Whenever i am making a request to web service endpoints from JsonP It is showing an strange behavior. In some machine i am getting an expected response where as in some other machine it continuously showing an error i.e. 405-method are not allowed.
I searched it for and make change according to them but nothing works for me. Please suggest me a solutoin
May be: I believe it had something to do with your jquery ajax call using jsonp. If you are going to change it to just json the post will work..