I'm new to .NET and WCF framework. Currently, I'm building a simple windows application to consume WCF service. The windows client need to pass username parameter to WCF Service to save to database. How can I do that without passing parameter in every service requests ?
One thing to note is this service will call a method in another project to save to database , so actually I want to access the username parameter at this project layer.
Form1.cs
public async void Save()
{
using(var client = new MyChannelFactory<WCFService>("WCFService"))
{
await Task.Run(() => client.Proxy.SaveData());
}
}
WCFService.cs
public void SaveData()
{
var _dataBL = new DataBL();
_dataBL.SaveData();
}
DataBL.cs
public void SaveData();
{
//need to get username from client
string user = GetUserName();
//save to database
}
Something to note:
WCFService.cs and DataBL.cs are in different projects.
I'm not adding Service Reference to client project, instead I'm using a ChannelFactory to create service proxy.
I'm using wsHttpBinding
I'm not using Windows Authentication
This should be a common request but after read many articles from internet, I still couldn't make it work.
Thanks for your help.
Related
We want to create an azure function in c# that retrieve the list of azure web app contained in the subscription (basically we want to call dynamically, for each webapp, the same API endpoint changing the subdomain of the api).
It's possible with c# retrieve the list of the web app contained in the same azure function subscriptions?
Usually we connect to the master database, we query the sys.databases to collect the dbname and understand the webapp names. But we are searching for a smartest way.
If you're in C# land, I'd look at using the ArmClient class to retrieve what you're looking for.
Install these (I've got a few others installed but start with that and see how you go, there may be a couple of others needed) Nuget packages ...
Azure.Identity;
Azure.ResourceManager;
Azure.ResourceManager.AppService
... and from there, using the DefaultCredential approach (if you've never used it, read up on it here -> https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/README.md) you can query your subscriptions webApps ...
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.AppService;
using System;
using System.Threading.Tasks;
namespace AzureManagement
{
internal class Program
{
static void Main(string[] args)
{
GetAzureResources().Wait();
}
static async Task GetAzureResources()
{
var credential = new DefaultAzureCredential();
var armClient = new ArmClient(credential);
var subscription = await armClient.GetDefaultSubscriptionAsync();
var webSitesEnumerator = subscription.GetWebSitesAsync().GetAsyncEnumerator();
try
{
while (await webSitesEnumerator.MoveNextAsync())
{
var webSite = webSitesEnumerator.Current;
Console.WriteLine($"Web App Name ........ {webSite.Data.Name}");
Console.WriteLine($"Default Host Name ... {webSite.Data.DefaultHostName}\n");
}
}
finally
{
await webSitesEnumerator.DisposeAsync();
}
Console.ReadLine();
}
}
}
The above is obviously not a function app but the core code will still work for you and can be ported as need be.
Note: I could be telling you how to suck eggs, but, once deployed to Azure, you'll need to do the necessary work to ensure that the function app has the required access to retrieve all of the resource information you're looking for.
If you're unfamiliar with that, read up on the managed identity concept. It's very easy to setup -> https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity
Yes, one easy way is to use HttpClient and send a request to Azure Rest API:
GET https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Web/sites?api-version=2022-03-01
https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/list
PS: you first need to acquire an authentication token.
https://www.youtube.com/watch?v=6b1J03fDnOg&t=329s
I want to implement SignalR with asmx webservice. The service is called from my front end application and my project is running.
My first question is, should I create SignalR hub here or I have to make another application for the Hub and use that for realtime purpose?
And second question is,
public class MyHub1: Hub
{
public bool ConnectUser(long userId)
{
UserManipulation Up = new UserManipulation();//its my class to process user//
return Up.ConnectUser(userId, Context.ConnectionId);
}
}
This is hub method to save the connection Id in database with the userid.
Now in asmx page, you know we have to create a [webmethod], so that I can call that method from front end. I want to create a webmethod which will call this hub method.
[WebMethod]
public bool ConnectUser(string UserId)
{
SignalRHub.MyHub1 myhub = new SignalRHub.MyHub1();//SignalRHub is namespace//
return myhub.ConnectUser(UserId);
}
But the context within the hub method getting null.
I don't know I'm in right way or not, but please help me how can I achieve the things to implement Hub not directly in front end, instead this type of service.
Currently we have a number of customers which use ASP.NET clients to call our various ASP.NET Web Services. We would like to migrate web services to WCF without touching customers' clients and their proxies. In addition we want to avoid using IIS for hosting services.
I've prepared simple prototype to examine if we are able to achieve such migration. This prototype works fine if only a simple namespace of web service is in use e.g. test.com. But because our ASP.NET services have namespaces like test.com/app1, test.com/app2 etc we need to build WCF services accordingly. Unfortunately when such address is used I get HTTP status 404 error while calling service's method.
After a few days of struggling I'm not sure if such migration is possible without hosting services on IIS (the IIS solution is http://msdn.microsoft.com/en-us/library/aa738697(v=vs.100).aspx).
Please, follow steps which I've done to prepare working prototype (with namespace test.com) and tell me where I'm wrong for extended namespace (like test.com/app).
1.
Initial ASP.NET web service:
[WebService(Namespace = "http://test.com")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class AspNetWebService : WebService
{
private static int _counter = 0;
[WebMethod]
public int Increment()
{
return _counter++;
}
}
2.
Deploy web service on IIS 7.0.
3.
Create simple ASP.NET client and generate proxy to web service (from step 1) by adding web reference in Visual Studio 2012 to asmx file of web service.
4.
Client calls Increment method properly, so I will not change this client to check if I may call WCF service.
5.
Create WCF service.
Contract:
[ServiceContract(Name = "IncrementService", Namespace = "http://test.com")]
public interface IIncrementService
{
[OperationContract(Action = "http://test.com/Increment")]
int Increment();
}
Service:
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
public class IncrementService : IIncrementService
{
private static int _counter = 0;
public int Increment()
{
return _counter++;
}
}
Self hosted in:
static void Main(string[] args)
{
const string httpAddress = "http://test.com";
var host = new ServiceHost(typeof(IncrementService), new Uri(httpAddress));
try
{
var metadataBehavior = host.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metadataBehavior == null)
metadataBehavior = new ServiceMetadataBehavior();
metadataBehavior.HttpGetEnabled = true;
host.Description.Behaviors.Add(metadataBehavior);
var httpBinding = new BasicHttpBinding();
httpBinding.Security.Mode = BasicHttpSecurityMode.None;
httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
host.AddServiceEndpoint(typeof(IIncrementService), httpBinding, httpAddress);
host.Open();
Console.ReadLine();
host.Close();
}
catch (Exception ex)
{
Console.WriteLine("An exception occurred: {0}", ex.Message);
host.Abort();
}
}
6.
Switch off IIS to be sure that ASP.NET web service doesn't work and start WCF service.
7.
Run the same client as before (without any changes or proxy regenerations) - it calls Increment properly.
So far so good... now I extend namespace.
8.
Add app name to namespace in ASP.NET web service as following:
[WebService(Namespace = "http://test.com/app")]
Switch on IIS again, switch off WCF service, regenerate proxy for client to work with new namespace - it calls Increment method properly again.
Change namespaces in WCF service as following:
Contract:
[ServiceContract(Name = "IncrementService", Namespace = "http://test.com/app")]
public interface IIncrementService
{
[OperationContract(Action = "http://test.com/app/Increment")]
int Increment();
}
In host application change httpAddress:
const string httpAddress = "http://test.com/app";
Switch off IIS, start WCF.
Try to call Increment method from the same client - exception occurs: The request failed with HTTP status 404: Not Found.
If I do not change httpAddress in step 10, then all works fine, but in such case I can host only one service on test.com domain. So this solution is not sufficient for us.
Finally I found the solution.
The httpAddress in step 10 should be set the same as URL of ASP.NET Web Service taken from ASP.NET client generated in step 3.
In my case, the URL of Web Service is (you may find it in client's app.config):
http://192.168.1.2/WS_simple/AspNetWebService.asmx
where WS_simple is ASP.NET application name hosted in IIS (created in step 2)
So I changed httpAddress to:
http://localhost/WS_simple/AspNetWebService.asmx
Maybe it's not nice address of WCF service but it works. So migration to WCF service without IIS with backward compatibility is done :)
I'm trying to route the request coming to my WCF to a different web service(3.5framework).. Is this even possible? If yes, please let me know the steps..
I need to Route from http://example.com/OldService.svc/Route to http://Newexample.com/NewService.svc/Request
Below are few of the things i tried..Most of the google search returns the routing for webforms and my requirement is for WEB SERVICES.
I tried with the following in my OldService project customroute handler: added a reference to the routing assembly, configured the web.config, added the below code in Global.asax
protected void Application_Start(object sender, EventArgs e)
{
RouteCollection routes = RouteTable.Routes;
//routes.Add("SOAP",new Route("soap", new WebServiceRouteHandler("~/Services/SoapQuery.asmx")));
routes.Add("SOAP", new Route("SOAP", new WebServiceRouteHandler("http://Newexample.com/NewService.svc/Request")));
}
Added a WebServiceRouteHandler as below
public class WebServiceRouteHandler: IRouteHandler
{
private string _VirtualPath;
public WebServiceRouteHandler(string virtualPath)
{
_VirtualPath = virtualPath;
}
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new WebServiceHandlerFactory().GetHandler(HttpContext.Current,
"*",
_VirtualPath,
HttpContext.Current.Server.MapPath(_VirtualPath));
}
}
I m calling the oldservice but I m still not redirected to the new Service. Please let me know if i m missing anything here..Should i add anything in my OldService Route method?
I am not sure exactly what you mean by redirect.
Are you saying you would like the Web Service client to be redirected to a new Web Service end point when i tries to contact the old Web Service?
This is not typically possible as services don't have the concept of "redirection." Not to mention if you even tried to redirect to the new service your endpoint bindings would no longer match and the service wouldn't fire anyway.
Is it possible to have the old service call the new service itself and return the results?
Such as Client -> connects to old service -> old service connects to new service -> old service returns the new service results to the client.
You also need to ensure you are returning the exact schema back to the client as it expects based on the WSDL or you will find problems reading the response.
Not sure if this helps at all...
I need some advice on what's the best way to create WCF client proxy wrapper for ASP .NET client. I want to work equally well with ObjectDataSource control with no extra coding and also when I need to manually call WCF service to get some data. I basically have come up with two models, but I'd like to know which is is more efficient.
Here is the first client wrapper
public class Facade1 : IDisposable
{
private readonly IClient proxy = ClientProxyFactory.GetObject<IClient>();
public List<string> GetData()
{
proxy.GetData()
}
public List<string> GetMoreData()
{
proxy.GetMoreData()
}
public void Dispose()
{
ClientProxyFactory.CloseChannel(this.proxy);
}
}
Now here is another WCF wrapper.
public class Facade2
{
public List<string> GetData()
{
IClient proxy = ClientProxyFactory.GetObject<IClient>();
try
{
return client.GetData();
}
finally
{
ClientProxyFactory.CloseChannel(proxy);
}
}
public List<string> GetMoreData()
{
IClient proxy = ClientProxyFactory.GetObject<IClient>();
try
{
return client.GetMoreData();
}
finally
{
ClientProxyFactory.CloseChannel(proxy);
}
}
}
In the first example, there is only one instance of the client proxy and it can be reused between various methods, but the class needs to implement IDisposable so that the proxy can be correctly disposed by the client. In the second example, there is one client proxy per method and the client does not have worry about disposing the proxy.
Is reusing proxy between different method a good way to go? Is there performance hit when you open/close WCF proxy? (In both examples, assume that ChannelFactory is cached and new channel is created every time via cached_factory.CreateChannel() method.)
For example, with the first wrapper I can do something like:
using (Facade1 facade = new Facade1())
{
facade.GetData()
...
...
facade.GetMoreData()
}
In the second example, I can just instantiate my facade and call the needed methods without worrying about disposing a proxy.
Thanks in advance,
Eric
If you use this wrapper for multiple calls to WCF service in single HTTP request processing in your ASP.NET application than the model with shared proxy is better. If you want to share the wrapper (make it global) then second model should be used.
Performance of recreating a proxy is dependent on type of used binding and its configuration. For example in case of BasicHttpBinding recreation of a proxy can be quick because there can still exists persistant HTTP connection from previous proxy. But in case of WSHttpBinding with security context, recreation of proxy means new security handshake for estabilishing security session.