When I add the following NuGet package to my WebJob: Microsoft.Azure.WebJobs.ServiceBus 2.0.0,
two new items are added to the app.config file.
It seems they are both used to define the Service Bus connection string.
Can I get rid of one of them?
<connectionStrings>
<add name="AzureWebJobsServiceBus" connectionString="..." />
</connectionStrings>
<appSettings>
<!-- Service Bus specific app setings for messaging connections -->
<add key="Microsoft.ServiceBus.ConnectionString" value="..." />
</appSettings>
Thanks for your help!
It seems they are both used to define the Service Bus connection string. Can I get rid of one of them?
According the source code of ServiceBusConfiguration, WebJob Service Bus SDK(ServiceBusTrigger) will use the connection string which stored under the connectionStrings section.
public string ConnectionString
{
get
{
if (!_connectionStringSet)
{
_connectionString = AmbientConnectionStringProvider.Instance.GetConnectionString(ConnectionStringNames.ServiceBus);
_connectionStringSet = true;
}
return _connectionString;
}
set
{
_connectionString = value;
_connectionStringSet = true;
}
}
You can also set the connection string at runtime.
JobHostConfiguration config = new JobHostConfiguration();
config.UseServiceBus(new ServiceBusConfiguration() { ConnectionString = "" });
JobHost host = new JobHost(config);
If you want to create a instance of Service Bus Client(for example QueueClient) to do some specific operations, you could use the Service Bus connection string configured in appSettings.
//Use CloudConfigurationManager to read the connection string stored in appSettings
string connectionString = CloudConfigurationManager.GetSetting("Microsoft.ServiceBus.ConnectionString");
var client = QueueClient.CreateFromConnectionString(connectionString, "queueName");
Related
I was trying to deploy an application in AWS elastic beanstalk with connection string inside web.config file everything works fine. But when I tried to implement by setting environment variables in AWS application it did not work. What I did was I added AWS tags key value pair in aws like RDS_DATABASENAME - admin then i added those in web.config like
<add key="RDS_DB_NAME" value="RDS_DB_NAME"/>
<add key="RDS_USERNAME" value="RDS_USERNAME"/>
<add key="RDS_PASSWORD" value="RDS_PASSWORD"/>
<add key="RDS_HOSTNAME" value="RDS_HOSTNAME"/>
<add key="RDS_PORT" value="*RDS_PORT" />
Then while building connectionString I used this:
var appConfig = ConfigurationManager.AppSettings; // trying to get connection details from enviornment varibales
string dbname = appConfig["RDS_DB_NAME"];
if (string.IsNullOrEmpty(dbname)) return null;
string username = appConfig["RDS_USERNAME"];
string password = appConfig["RDS_PASSWORD"];
string hostname = appConfig["RDS_HOSTNAME"];
string port = appConfig["RDS_PORT"];
SqlConnectionStringBuilder sqlString = new SqlConnectionStringBuilder()
{
DataSource = hostname + "," + port,
InitialCatalog = dbname,
UserID = username,
Password = password
};
return sqlString.ToString();
I followed the aws doc itself somehow I missed something!
The idea with Elastic Beanstalk is that any Environment Properties configured for the Environment will be automatically passed to your application. In a .NET application, this means that they are appended automatically to the end of the <appSettings> section of the Web.config.
So you shouldn't need to make any changes to your Web.config (I would leave those variables out entirely), and your implementation of building the connectionString appears fine.
To troubleshoot, try launching the application with the Environment Properties set. Then log into the instance and verify that the variables have been added to the Web.config correctly. If they are you might need to do some more testing around making sure your application is reading them in correctly.
I'm a newbie on WCF. I'm able to build a self-hosted WCF service and 4 .NET applications connected to it using NetTcpBindings. Now I need one more client written in Python2.7 script to connect to this WCF service providing duplex communication.
As far as I googled, WsDualHttpBinding with SOAP 1.2 should be used.
Here is my service interface
namespace GPH_QuickMessageServiceLib
{
/// <summary>
/// GPH Quick Message Service Operations
/// </summary>
[ServiceContract(
Name = "GPH_QuickMessageService",
Namespace = "GPH_QuickMessageServiceLib",
SessionMode = SessionMode.Required,
CallbackContract = typeof(IMessageServiceCallback))]
public interface IMessageServiceInbound
{
[OperationContract]
[WebInvoke]
int JoinTheConversation(string userName);
[OperationContract]
[WebInvoke]
int LeaveTheConversation(string userName);
}
public interface IMessageServiceCallback
{
[OperationContract(IsOneWay = true)]
[WebInvoke]
void NotifyUserJoinedTheConversation(string userName, List<string> SubscriberList);
[OperationContract(IsOneWay = true)]
[WebInvoke]
void NotifyUserLeftTheConversation(string userName, List<string> SubscriberList);
}
}
Here is my service behavior
namespace GPH_QuickMessageServiceLib
{
/// <summary>
/// GPH Quick Message Service behaviour
/// </summary>
[ServiceBehavior(
ConcurrencyMode = ConcurrencyMode.Single,
InstanceContextMode = InstanceContextMode.PerCall)]
public class GPH_QuickMessageService : IMessageServiceInbound
{
private static List<IMessageServiceCallback> _callbackList = new List<IMessageServiceCallback>();
// number of current users - 0 to begin with
private static int _registeredUsers = 0;
private static List<string> SubscriberList = new List<string>();
private static Dictionary<string, IMessageServiceCallback> NotifyList = new Dictionary<string, IMessageServiceCallback>(); // Default Constructor
// Default Constructor
public GPH_QuickMessageService() { }
public int JoinTheConversation(string userName)
{
// Subscribe the user to the conversation
IMessageServiceCallback registeredUser = OperationContext.Current.GetCallbackChannel<IMessageServiceCallback>();
if (!_callbackList.Contains(registeredUser))
{
_callbackList.Add(registeredUser);
SubscriberList.Add(userName);//Note the callback list is just a list of channels.
NotifyList.Add(userName, registeredUser);//Bind the username to the callback channel ID
}
_callbackList.ForEach(
delegate (IMessageServiceCallback callback)
{
callback.NotifyUserJoinedTheConversation(userName, SubscriberList);
_registeredUsers++;
});
return _registeredUsers;
}
public int LeaveTheConversation(string userName)
{
// Unsubscribe the user from the conversation.
IMessageServiceCallback registeredUser = OperationContext.Current.GetCallbackChannel<IMessageServiceCallback>();
if (_callbackList.Contains(registeredUser))
{
_callbackList.Remove(registeredUser);
NotifyList.Remove(userName);
SubscriberList.Remove(userName);
_registeredUsers--;
}
// Notify everyone that user has arrived.
// Use an anonymous delegate and generics to do our dirty work.
_callbackList.ForEach(
delegate (IMessageServiceCallback callback)
{
callback.NotifyUserLeftTheConversation(userName, SubscriberList);
});
return _registeredUsers;
}
}
}
Here is my App.config in service-host application
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<system.serviceModel>
<services>
<service name="GPH_QuickMessageServiceLib.GPH_QuickMessageService"
behaviorConfiguration = "QuickMessageServiceMEXBehavior">
<endpoint address ="soap"
binding="wsDualHttpBinding"
contract="GPH_QuickMessageServiceLib.IMessageServiceInbound" />
<endpoint address ="service"
binding="netTcpBinding"
contract="GPH_QuickMessageServiceLib.IMessageServiceInbound" />
<!-- Enable the MEX endpoint -->
<endpoint address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange" />
<!-- Need to add this so MEX knows the address of our service -->
<host>
<baseAddresses>
<add baseAddress="http://localhost:2709/GPH_QuickMessageService/soap"/>
<add baseAddress="net.tcp://localhost:8868/GPH_QuickMessageService"/>
</baseAddresses>
</host>
</service>
</services>
<!-- A behavior definition for MEX -->
<behaviors>
<serviceBehaviors>
<behavior name="QuickMessageServiceMEXBehavior" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
And here is what I have in Python2.7 script (I'm using suds-jurko 0.6 with a hack to use SOAP 1.2 as .NET wsDualHttpBinding only supports SOAP 1.2)
from suds.client import Client
from suds.bindings import binding
import logging
# Just for debugging purposes.
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
# Telnic's SOAP server expects a SOAP 1.2 envelope, not a SOAP 1.1 envelope
# and will complain if this hack isn't done.
binding.envns = ('SOAP-ENV', 'http://www.w3.org/2003/05/soap-envelope')
client = Client('http://localhost:2709/GPH_QuickMessageService/soap?wsdl',
headers={'Content-Type': 'application/soap+xml'})
# This will now work just fine.
result = client.service.JoinTheConversation('RIDE')
print client
print 'result = %s' % result
As i guess, my python client already bound to server and get the list of available operations but it could not get the result from those operations. It always returns None
C:\Python27\python.exe C:/Users/sev_user/PycharmProjects/WcfInteration/venv/Scripts/suds_client.py
DEBUG:suds.client:sending to (http://localhost:2709/GPH_QuickMessageService/soap/soap)
message:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="GPH_QuickMessageServiceLib" xmlns:ns1="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
<SOAP-ENV:Header/>
<ns1:Body>
<ns0:JoinTheConversation>
<ns0:userName>RIDE</ns0:userName>
</ns0:JoinTheConversation>
</ns1:Body>
</SOAP-ENV:Envelope>
DEBUG:suds.client:headers = {'SOAPAction': '"GPH_QuickMessageServiceLib/GPH_QuickMessageService/JoinTheConversation"', 'Content-Type': 'application/soap+xml'}
Suds ( https://fedorahosted.org/suds/ ) version: 0.6
Service ( GPH_QuickMessageService ) tns="http://tempuri.org/"
Prefixes (3)
ns0 = "GPH_QuickMessageServiceLib"
ns1 = "http://schemas.microsoft.com/2003/10/Serialization/"
ns2 = "http://schemas.microsoft.com/2003/10/Serialization/Arrays"
Ports (2):
(WSDualHttpBinding_GPH_QuickMessageService)
Methods (7):
JoinTheConversation(xs:string userName)
LeaveTheConversation(xs:string userName)
NotifyUserJoinedTheConversation()
NotifyUserLeftTheConversation()
NotifyUserOfMessage()
ReceiveMessage(xs:string userName, ns2:ArrayOfstring addressList, xs:string userMessage)
sum(xs:int a, xs:int b)
Types (4):
ns2:ArrayOfstring
ns1:char
ns1:duration
ns1:guid
(NetTcpBinding_GPH_QuickMessageService)
Methods (7):
JoinTheConversation(xs:string userName)
LeaveTheConversation(xs:string userName)
NotifyUserJoinedTheConversation()
NotifyUserLeftTheConversation()
NotifyUserOfMessage()
ReceiveMessage(xs:string userName, ns2:ArrayOfstring addressList, xs:string userMessage)
sum(xs:int a, xs:int b)
Types (4):
ns2:ArrayOfstring
ns1:char
ns1:duration
ns1:guid
result = None
DEBUG:suds.client:HTTP succeeded:
Process finished with exit code 0
I have tried several ways other than suds, such as ZSI, zeep, but always get result as 'None' or '0'. I have attached logger on these SOAP client process and always get either 'HTTP succeed' or '202 Accepted'. Couldn't figure out myself what should be wrong here.
Did any body face the same problem? Please give me some clue to resolve this.
Or any other idea to get duplex communication between Python2.7 and WCF is always appreciated.
I have an asmx web service, which I am trying to verify client certificate:
var cert = Context.Request.ClientCertificate.Certificate;
if (cert == null || cert.Length == 0)
{
throw new ArgumentException("certificate can not be found");
}
My testing code is like this in a console app:
ServiceReference1.PortfolioImportSoapClient import = new ServiceReference1.PortfolioImportSoapClient();
X509Certificate2 x509 = new X509Certificate2(#"D:\zurichpdf\publickey.cer");
import.ClientCredentials.ClientCertificate.Certificate = x509;
var model = new ServiceReference1.PortfolioMessageModel();
model.ClientID = 1;
import.ImportTransactionPortfolio(model);
What I can see is that from the console app, the client certificate is included. But at the server side, Context.Request.ClientCertificate.Certificate is empty.
I checked the config file, it has something like this:
<basicHttpBinding>
<binding name="PortfolioImportSoap" >
</binding>
</basicHttpBinding>
Can someone tell me why the x509 certificate is not passed to my asmx web service? Should I set some security mode here as well?
Many Thanks
I have an MVC web applicationt that has been confuigured to connect to ADFS to authenticate users and get a security token. The application then needs to call a WCF service using that security token.
The config of the web app is
<system.identityModel>
<identityConfiguration saveBootstrapContext="true">
<claimsAuthenticationManager type="MvcApplication1.Security.ClaimsTransformer, MvcApplication1" />
<claimsAuthorizationManager type="MvcApplication1.Security.AuthorisationManager, MvcApplication1" />
<audienceUris>
<add value="https://edd05rgard.hd.dev/adfsproto/web/" />
</audienceUris>
<issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<trustedIssuers>
<add thumbprint="49F27C0DD1044D73011894450727E3C3E55DA428" name="http://EDV05TESTADFS1.hdtest.hd.dev/adfs/services/trust" />
</trustedIssuers>
</issuerNameRegistry>
</identityConfiguration>
<federationConfiguration>
<cookieHandler requireSsl="true" />
<wsFederation passiveRedirectEnabled="true"
issuer="https://edv05testadfs1.hdtest.hd.dev/adfs/ls/"
realm="https://edd05rgard.hd.dev/adfsproto/web/"
reply="https://edd05rgard.hd.dev/adfsproto/web/"
requireHttps="true" />
</federationConfiguration>
This successfully gets the token from ADFS and I can transform claims within the app as expected.
I then try to make a call to a WCF service using the supplied security token:
BootstrapContext bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as BootstrapContext;
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.IssuedKeyType = SecurityKeyType.BearerKey;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.IssuerAddress = new EndpointAddress("https://edv05testadfs1.hdtest.hd.dev/adfs/ls");
var endpoint = new EndpointAddress("https://edd05rgard.hd.dev/adfsproto/service/ClaimsService.svc");
var factory = new ChannelFactory<IClaimsService>(binding, endpoint);
factory.Credentials.SupportInteractive = false;
factory.Credentials.UseIdentityConfiguration = true;
var context = (BootstrapContext)((ClaimsIdentity)Thread.CurrentPrincipal.Identity).BootstrapContext;
var channel = factory.CreateChannelWithIssuedToken(context.SecurityToken, endpoint);
var result = channel.GetClaimsWithDelegation();
When this code is executed the last line causes an exception:
An error occurred when processing the security tokens in the message.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ServiceModel.FaultException: An error occurred when processing the security tokens in the message.
Am I calling the service in the correct way? How can I investigate the errors in the security token?
After I got my single-page web app working (web pages served with ServiceStack's RazorFormat() MVC, not .ASP MVC), I ran a (previously passing) test for the service. The test failed. Tested the web app again (debug run, navigate to //localhost:1337/ResourceList in the browser): still working. Is something wrong with my test?
Here's the error:
Test Name: TestResourceList
Test FullName: [0-1015]ServiceWrapper.Test.TestSWrapperServices.TestResourceList
Test Source: c:\Users\uname\Documents\Visual Studio 2012\Projects\ServiceWrapper\UnitTestProject1\ServiceTests.cs : line 96
Test Outcome: Failed
Test Duration: 0:00:02.188
Result Message:
System.Net.WebException : Unable to connect to the remote server
----> System.Net.Sockets.SocketException : No connection could be made because the target machine actively refused it 127.0.0.1:1337
Result StackTrace:
at System.Net.HttpWebRequest.GetResponse()
at ServiceStack.ServiceClient.Web.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request)
at ServiceStack.ServiceClient.Web.ServiceClientBase.Get[TResponse](IReturn`1 request)
at ServiceWrapper.Test.TestSWrapperServices.TestResourceList() in c:\Users\uname\Documents\Visual Studio 2012\Projects\ServiceWrapper\UnitTestProject1\ServiceTests.cs:line 98
--SocketException
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)
Here's the test:
namespace ServiceWrapper.Test
{
[TestFixture]
public class TestSWrapperServices
{
AppHost appHost;
private const string ListeningOn = "http://*:1337/";
public const string Host = "http://localhost:1337";
private const string BaseUri = Host + "/";
[TestFixtureSetUp]
public void OnTestFixtureSetUp()
{
var appSettings = new AppSettings();
var username = Environment.GetEnvironmentVariable("USERNAME");
var userdomain = Environment.GetEnvironmentVariable("USERDOMAIN");
AppHost.AppConfig = new AppConfig(new AppSettings());
appHost = new AppHost();
// initialize Service Server
ServiceServer.SetUser(AppHost.AppConfig.UserName, AppHost.AppConfig.Password);
ServiceServer.SetLog(String.Empty);
try
{
appHost.Init();
appHost.Start(ListeningOn);
}
catch (HttpListenerException ex)
{
if (ex.ErrorCode == 5)
{
System.Diagnostics.Debug.WriteLine("You need to run the following command (as admin):");
System.Diagnostics.Debug.WriteLine(" netsh http add urlacl url={0} user={1}\\{2} listen=yes",
ListeningOn, userdomain, username);
}
else
{
System.Diagnostics.Debug.WriteLine("ERROR: {0}: {1}", ex.GetType().Name, ex.Message);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("ERROR: {0}: {1}", ex.GetType().Name, ex.Message);
}
}
[TestFixtureTearDown]
public void OnTestFixtureTearDown()
{
appHost.Dispose();
}
[Test]
public void TestResourceList()
{
JsonServiceClient client = new JsonServiceClient(BaseUri);
ResourceList response = client.Get(new ResourceList());
Assert.Contains("Some Value", response.property);
}
[Test]
}
}
I upgraded to the latest ServiceStack - 3.9.55, and it still didn't work. So, I started over again, sanity checking from the beginning. It turns out that the program.cs ListeningOn has http://*:1337/ while the nunit TestFixture ListeningOn was http://localhost:1337/
Checking urlacl (as admin) for http://localhost:1337/:
C:\Windows\system32>netsh http show urlacl url=http://localhost:1337/
URL Reservations:
-----------------
Checking urlacl (as admin) for http://*:1337/:
C:\Windows\system32>netsh http show urlacl url=http://*:1337/
URL Reservations:
-----------------
Reserved URL : http://*:1337/
User: DOMAIN\user
Listen: Yes
Delegate: No
SDDL: D:(A;;GX;;;S-1-5-21-2595267603-2801715271-1705165942-1002)
My earlier troubleshooting left the two projects with inconsistent ListeningOn values. Interestingly, using http://*:1337/ doesn't work as a wildcard url, as perhaps I had expected.
Here's a handy code snippet to help you build the add urlacl command. It also provides a useful (!) sanity check on the exact url you're listening on.
Console.WriteLine("You need to run the following command:");
Console.WriteLine(" netsh http add urlacl url={0} user={1}\\{2} listen=yes",
ListeningOn, userdomain, username);
--- Update ---
Upgrading ServiceStack eliminated the 'connection actively refused' error message. Once ListeningOn values were unified, the real
error message was exposed:
Result Message: ServiceStack.ServiceClient.Web.WebServiceException : Service Unavailable
Result StackTrace:
at ServiceStack.ServiceClient.Web.ServiceClientBase.ThrowWebServiceException[TResponse](Exception ex, String requestUri)
at ServiceStack.ServiceClient.Web.ServiceClientBase.ThrowResponseTypeException[TResponse](Object request, Exception ex, String requestUri)
at ServiceStack.ServiceClient.Web.ServiceClientBase.HandleResponseException[TResponse](Exception ex, Object request, String requestUri, Func`1 createWebRequest, Func`2 getResponse, TResponse& response)
at ServiceStack.ServiceClient.Web.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request)
at ServiceStack.ServiceClient.Web.ServiceClientBase.Get[TResponse](IReturn`1 request)
at RemoteServerWrapper.Test.TestRSWrapperServices.TestDataList() in c:\Users\user\Documents\Visual Studio 2012\Projects\RemoteServerWrapper\UnitTestProject1\ServiceTests.cs:line 183
It's still obscure -- but at least it's not reporting something that's completely different from the real issue. So then I implemented trace in my app.config, like this:
<configuration>
<!-- ... other config settings ... -->
<system.diagnostics>
<sources>
<source name="System.Net" tracemode="includehex" maxdatasize="1024">
<listeners>
<add name="System.Net"/>
<add name="console"/>
</listeners>
</source>
<source name="System.Net.HttpListener">
<listeners>
<add name="System.Net"/>
<add name="console"/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.HttpListener" value="Verbose"/>
</switches>
<sharedListeners>
<add name="console"
type="System.Diagnostics.ConsoleTraceListener"
initializeData="false"/>
<add name="System.Net"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="network.log"
/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>
</configuration>
Which exposed a better error message:
ERROR: [::1]:1337 Request not found: /datarequest?DataKey=some_key&startDate=20130701&endDate=20130708
OK - now I have to pull in the servicestack sources so I can step through the code and figure out why I'm getting 'Not Found' in the test, when it works when I 'debug/run' and test via the browser. Turns out that RestHandler.FindMatchingRestPath(httpMethod, pathInfo, contentType) wasn't returning a match. Humm. Why is that? The AppHost is declared identically. So, what's different?
The rest services live in my project's main assembly. When run from 'debug/run' the default assembly has the services, and everything works. But when run from the test project, with the services assembly added as a reference, servicestack can't find them. They're not in the default location, relative to the test project. So I added an AppHost class at the top of my test file, rather than relying on the one from my program.cs, and declared it as follows:
public class RSWrapperServicesAppHostHttpListener
: AppHostHttpListenerBase
{
public RSWrapperServicesAppHostHttpListener()
: base("RSWrapper Services Tests", typeof(DataRequestService).Assembly) { }
// 'DataRequestService' is a random rest service class,
// defined in the referenced services assembly
}
Now ServiceStack is happy, and my tests work again.
How did they ever work? Originally everything was jumbled together all in one project. Once I separated things into separate assemblies, i.e. DTO, Services, Business Logic and Tests, I broke it. But since I was temporarily holding off on unit tests while getting the UI working, I didn't notice right away.