how to use external (free available or paid) web services - web-services

how to use the external web service (paid or free) in the application.
For example:
Here is the code snippet from one of the site (http://debugmode.net/2010/09/10/consuming-wcf-rest-service-in-asp-net-web-site/) which is using the self created service. But instead of it if one has to use the external service how should be proceeded?
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
WebClient proxy = new WebClient();
byte[] abc = proxy.DownloadData((new Uri("http://localhost:4567/Service1.svc/GetData")));
Stream strm = new MemoryStream(abc);
DataContractSerializer obj = new DataContractSerializer(typeof(string));
string result = obj.ReadObject(strm).ToString();
TextBox1.Text = result;
}

Related

How to debug a WCF call when it's a singleton and being run in a test

I am self-hosting a duplex-contract, WCF service.
In composing a test that exercises if my client is receiving messages from the service, I have found that I can't debug the service itself.
Thus, I made a simple example that seems to help me repeat the issue.
This is an example of the test I'm attempting:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
ServiceRunner.Run(null);
var client = new ServiceReference1.Service1Client();
var result = client.GetData(11);
Assert.IsNotNull(result);
ServiceRunner.Host.Close();
}
}
ServiceRunner will host the WCF contract in a singleton. The client is from a service reference that points to the self-hosted service. When I call GetData(11) I get a response, it's just that my breakpoint in the service is never hit.
Why is that?
Here's the implementation of the service for completeness:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Text;
namespace CanYouDebugThis
{
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
[ServiceBehaviorAttribute(InstanceContextMode = InstanceContextMode.Single)]
public class Service1 : IService1
{
public string GetData(int value)
{
Console.WriteLine($"Get data with {value}");
return string.Format("You entered: {0}", value);
}
}
public class ServiceRunner
{
public static ServiceHost Host;
public static void Run(String[] args)
{
var serviceInstance = new Service1();
Uri baseAddress = new Uri("http://localhost:8080/hello");
Host = new ServiceHost(serviceInstance, baseAddress);
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
Host.Description.Behaviors.Add(smb);
Host.Open();
}
}
}
There is something wrong with hosting the service. We should add service endpoint and MEX endpoint for exchanging metadata. Please refer to the below code segments.
public static ServiceHost Host;
public static void Main(String[] args)
{
var serviceInstance = new Service1();
Uri baseAddress = new Uri("http://localhost:8080/hello");
BasicHttpBinding binding = new BasicHttpBinding();
//Host = new ServiceHost(serviceInstance, baseAddress);
Host = new ServiceHost(typeof(Service1), baseAddress);
Host.AddServiceEndpoint(typeof(IService1), binding, "");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
Host.Description.Behaviors.Add(smb);
Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
Host.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");
Host.Open();
Console.WriteLine("Service is ready...");
//pause, accepting a word would teminate the service.
Console.ReadLine();
Host.Close();
Console.WriteLine("Service is closed....");
}
Please host the service in an individual Console project first. Then on the client-side, we generate the client proxy by adding the service reference. Please pay attention to the auto-generated service endpoint, which should be corresponding to the actual server endpoint.
Result.
Feel free to let me know if there is anything I can help with.
Updated.
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
ServiceRunner.Run(null);
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
var result = client.GetData(34);
Assert.IsNotNull(result);
}
}
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
[ServiceBehaviorAttribute(InstanceContextMode = InstanceContextMode.Single)]
public class Service1 : IService1
{
public string GetData(int value)
{
Console.WriteLine($"Get data with {value}");
return string.Format("You entered: {0}", value);
}
}
public class ServiceRunner
{
public static ServiceHost Host;
public static void Run(String[] args)
{
var serviceInstance = new Service1();
Uri baseAddress = new Uri("http://localhost:8080/hello");
Host = new ServiceHost(serviceInstance, baseAddress);
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
Host.Description.Behaviors.Add(smb);
Host.Open();
}
}
Result.
At last, please pay attention to the automatically generated client endpoint address.

How to manage secret rotation used by spring boot app running on ECS in AWS cloud

My organization is running spring boot app on AWS ECS docker container which reads the credentials for Postgres sql from secrets manager in AWS during boot up. AS part of security complaince, we are rotating the secrets every 3 months. The spring boot app is loosing connection with the database and going down when the RDS credentials are rotated.we have to restart it in order to pick the new credentials to work properly. Is there any way I can read the credentials automatically once the credentials are rotated to avoid restarting the application manually?
After some research I found that the postgres database in AWS supports passwordless authentication using IAM roles. We can generate a token which is valid for 15 mins and can connect to database using that token. I prefer this way of connecting to database rather than using password for my database. More details about setting up password less authentication can be found here
Code example as below
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.services.rds.auth.GetIamAuthTokenRequest;
import com.amazonaws.services.rds.auth.RdsIamAuthTokenGenerator;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.jdbc.pool.ConnectionPool;
import org.apache.tomcat.jdbc.pool.PoolConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.net.URISyntaxException;
import java.sql.SQLException;
import java.util.Properties;
public class RdsIamAuthDataSource extends org.apache.tomcat.jdbc.pool.DataSource {
private static final Logger LOGGER = LoggerFactory.getLogger(RdsIamAuthDataSource.class);
private static final int DEFAULT_PORT = 5432;
private static final String USESSL = "useSSL";
private static final String REQUIRE_SSL = "requireSSL";
private static final String BOOLEAN_TRUE = "true";
private static final String VERIFY_SERVER_CERTIFICATE = "verifyServerCertificate";
private static final String THREAD_NAME = "RdsIamAuthDataSourceTokenThread";
/**
* Constructor for RdsIamAuthDataSource.
* #param props {#link PoolConfiguration}
*/
public RdsIamAuthDataSource(PoolConfiguration props) {
this.poolProperties = props;
}
#Override
public ConnectionPool createPool() throws SQLException {
if (pool == null) {
return createPoolImpl();
} else {
return pool;
}
}
protected ConnectionPool createPoolImpl() throws SQLException {
synchronized (this) {
return pool = new RdsIamAuthConnectionPool(poolProperties);
}
}
private class RdsIamAuthConnectionPool extends ConnectionPool implements Runnable {
private RdsIamAuthTokenGenerator rdsIamAuthTokenGenerator;
private String host;
private String region;
private int port;
private String username;
private Thread tokenThread;
/**
* Constructor for RdsIamAuthConnectionPool.
* #param prop {#link PoolConfiguration}
* #throws SQLException {#link SQLException}
*/
public RdsIamAuthConnectionPool(PoolConfiguration prop) throws SQLException {
super(prop);
}
#Override
protected void init(PoolConfiguration prop) throws SQLException {
try {
final URI uri = new URI(prop.getUrl().substring(5));
this.host = uri.getHost();
this.port = uri.getPort();
if (this.port < 0) {
this.port = DEFAULT_PORT;
}
this.region = StringUtils.split(this.host,'.')[2];
this.username = prop.getUsername();
this.rdsIamAuthTokenGenerator = RdsIamAuthTokenGenerator.builder()
.credentials(new DefaultAWSCredentialsProviderChain())
.region(this.region)
.build();
updatePassword(prop);
final Properties props = prop.getDbProperties();
props.setProperty(USESSL, BOOLEAN_TRUE);
props.setProperty(REQUIRE_SSL, BOOLEAN_TRUE);
props.setProperty(VERIFY_SERVER_CERTIFICATE, BOOLEAN_TRUE);
super.init(prop);
this.tokenThread = new Thread(this, THREAD_NAME);
this.tokenThread.setDaemon(true);
this.tokenThread.start();
} catch (URISyntaxException e) {
LOGGER.error("Database URL is not correct. Please verify", e);
throw new RuntimeException(e.getMessage());
}
}
/**
* Refresh the token every 12 minutes.
*/
#Override
public void run() {
try {
while (this.tokenThread != null) {
Thread.sleep(12 * 60 * 1000);
updatePassword(getPoolProperties());
}
} catch (InterruptedException e) {
LOGGER.error("Background token thread interrupted", e);
}
}
#Override
protected void close(boolean force) {
super.close(force);
final Thread thread = tokenThread;
if (thread != null) {
thread.interrupt();
}
}
private void updatePassword(PoolConfiguration props) {
final String token = rdsIamAuthTokenGenerator.getAuthToken(GetIamAuthTokenRequest.builder()
.hostname(host)
.port(port)
.userName(this.username)
.build());
LOGGER.info("Updated IAM token for connection pool");
props.setPassword(token);
}
}
}
Supply the following DataSource as a spring bean. That's it. Now your application will automatically refresh credentials every 12 minutes
#Bean
public DataSource dataSource() {
final PoolConfiguration props = new PoolProperties();
props.setUrl("jdbc:postgresql://myapp.us-east-2.rds.amazonaws.com/myschema?ssl=true");
props.setUsername("rdsadminuser");
props.setDriverClassName("org.somedatabase.Driver");
return new RdsIamAuthDataSource(props);
}

Use KCL 1.* in Lambda: Credentials

Using the examples provided in https://github.com/aws/aws-sdk-java/tree/master/src/samples/AmazonKinesis I understand how to use the KCL to read KinesisEvents from my local machine.
I am trying to implement the same logic in Lambda Functions.
To set up the KinesisClientLibConfiguration, you need to provide an AWSCredentialsProvider.
Where do I get these AWSCredentials to create the kinesisClientLibConfiguration in a Lambda?
KinesisClientLibConfiguration kinesisClientLibConfiguration = new KinesisClientLibConfiguration(SAMPLE_APPLICATION_NAME, SAMPLE_APPLICATION_STREAM_NAME, credentialsProvider, workerId);
The full code of the handler looks like this:
public class ProcessKinesisRecords implements RequestHandler<KinesisEvent, Void> {
public static final String SAMPLE_APPLICATION_STREAM_NAME = "kinesis-s";
public static final String SAMPLE_APPLICATION_STREAM_REGION = "eu-west-1";
private static final String SAMPLE_APPLICATION_NAME = "SampleKinesisLambdaApplication";
private static final InitialPositionInStream SAMPLE_APPLICATION_INITIAL_POSITION_IN_STREAM =
InitialPositionInStream.LATEST;
private static ProfileCredentialsProvider credentialsProvider;
public Void handleRequest(KinesisEvent event, Context context) {
init();
int exitCode = 0;
try {
String workerId = InetAddress.getLocalHost().getCanonicalHostName() + ":" + UUID.randomUUID();
KinesisClientLibConfiguration kinesisClientLibConfiguration =
new KinesisClientLibConfiguration(SAMPLE_APPLICATION_NAME,
SAMPLE_APPLICATION_STREAM_NAME,
credentialsProvider,
workerId);
kinesisClientLibConfiguration.withInitialPositionInStream(SAMPLE_APPLICATION_INITIAL_POSITION_IN_STREAM);
kinesisClientLibConfiguration.withRegionName(SAMPLE_APPLICATION_STREAM_REGION);
IRecordProcessorFactory recordProcessorFactory = new AmazonKinesisApplicationRecordProcessorFactory();
Worker worker = new Worker(recordProcessorFactory, kinesisClientLibConfiguration);
System.out.printf("Running %s to process stream %s as worker %s...\n",
SAMPLE_APPLICATION_NAME,
SAMPLE_APPLICATION_STREAM_NAME,
workerId);
worker.run();
} catch (Throwable e) {
System.err.println("Caught throwable while processing data.");
e.printStackTrace();
}
System.exit(exitCode);
return null;
}
private static void init() {
// Ensure the JVM will refresh the cached IP values of AWS resources (e.g. service endpoints).
java.security.Security.setProperty("networkaddress.cache.ttl", "60");
credentialsProvider = new ProfileCredentialsProvider();
try {
credentialsProvider.getCredentials();
} catch (Exception e) {
throw new AmazonClientException("Cannot load the credentials", e);
}
}
}
Lambda does provide environment variables for the credentials:
https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html#lambda-environment-variables
Access them via the EnvironmentVariableCredentialsProvider:
https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/auth/EnvironmentVariableCredentialsProvider.java

How to get header value in UploadStringCompletedEventHandler method ASP.NET (Web API Service using HttpClient)

In My Windows Phone 8 App, I create WebClient object and initiate the with UploadStringAsync. and Create webClientLogin.UploadStringCompleted using UploadStringCompletedEventHandler.
WebClient webClientLogin = new WebClient();
webClientLogin.Headers["content-type"] = "application/json";
webClientLogin.UploadStringCompleted += new UploadStringCompletedEventHandler(webClientUploadStringCompleted);
webClientLogin.UploadStringAsync(new Uri(URL + "LogIn"), "POST", stockiestData);
Here stockiestData is Encoded Using Encoding.UTF8
I Get response as well.
private void webClientUploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
var logindetails = JsonConvert.DeserializeObject<LogResponse>(e.Result);
}
But I need to get the Header in this above method (webClientUploadStringCompleted).
I send the header like follows HttpContext.Current.Response.AppendHeader("Msg","Checked");
This response created in WebApi
How to get this?
Able to get header values using sender Object in the following method.
private void webClientUploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
}
We have to cast this object as WebClient.
Following method shows how to send in WebApi
[HttpPost]
[ActionName("LogIn")]
public dynamic LogIn(List<Student> Student, HttpRequestMessage request)
{
if (Student!= null)
{
HttpContext.Current.Response.AppendHeader("Msg", "Resived");
}
Following code shows you how to get header value from Windows phone 8
private void webClientUploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
WebClient web = (WebClient)sender;
WebHeaderCollection myWebHeaderCollection = (WebHeaderCollection)web.ResponseHeaders;
var v = web.ResponseHeaders["Msg"];
}

How to get data from web service in window phone 8

private void GetData()
{
StudentWS.StudentWSSoapClient MyClient = new StudentWS.StudentWSSoapClient();
MyClient.GetStudentCompleted +=MyClient_GetStudentCompleted;
MyClient.GetStudentAsync(CONNECTION_KEY);
}
void MyClient_GetStudentCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
}
How to get the data from the method in webservice