I started working on Microservices. So I have made two Restful APIs.
Organisations API ( GET, PUT, POST, DELETE )
Customers API ( GET, PUT, POST, DELETE )
These two are separate APIs and hosted on different ports on my local IIS.
Now I want to consume them in my main application.
So the requirement is to call them only by Network connection.
I found that I need to use Rpc, gRpc or Kafka.
so, I have decided to use Rpc by using RabbitMq and EasyNetQ.
By this, I have configured rabbiqMq in docker and it is running successfully.
What I am not understanding is that in my Organisations and Customers API there are multiple actions. GET, PUT, POST, DELETE
So, Where I need to define the queue name for those method, so I can consume it in my main app by calling with some name. and it will directly call that method.
e.g.
var factory = new ConnectionFactory() { HostName = "localhost" };
var connection = factory.CreateConnection();
var channel = connection.CreateModel();
var body = Encoding.UTF8.GetBytes(entity);
channel.BasicPublish(exchange: "organisations", routingKey: "organisations.add", basicProperties: null, body: body);
Where in the organisations api, I will define this organisations.add, organisations.update, organisations.search ?
Can I add them dynamically through some mediator ?
Or I need to add manually in the rabitmq ui .. to adding queue ?
I usually use IBus.Publish for publishing message it supports strong type and also it detects the Exchange and Queue name automatically.
Let's assume you have a Message class for adding organizations like this:
[Queue("Organisations.Add", ExchangeName = "Organisations.Add")]
public class Message
{
public string Text { get; set; }
public DateTime Date { get; set; }
}
And for publish a message to broker:
using (var bus = RabbitHutch.CreateBus("host=localhost"))
{
var message = new Message() { Text = "Hello World", Date = DateTime.Now };
bus.Publish<Message>(message);
}
So you can create multiple messages based on api and use them in Mediator.
Related
Currently, I have to switch our messaging system to use AmazonSQS and due to pricing policy, we are obliged to put tags. But I do not found any method to add tags.
Below the method which won't work due to fact that this approach is expecting that the queues already exist and I can get URL of the queue:
public static EndpointConfiguration CreateEndpointConfiguration(BusConfig config)
{
var endpointConfiguration = new EndpointConfiguration(config.QueueName);
endpointConfiguration.LicensePath("license.xml");
endpointConfiguration.SendFailedMessagesTo($"{config.QueueName}.Errors");
endpointConfiguration.EnableInstallers();
endpointConfiguration.UseSerialization<NewtonsoftSerializer>();
endpointConfiguration.LimitMessageProcessingConcurrencyTo(10);
endpointConfiguration.Conventions()
.DefiningEventsAs(type => typeof(IMessage).IsAssignableFrom(type))
.DefiningCommandsAs(type => typeof(ICommand).IsAssignableFrom(type));
var transport = endpointConfiguration.UseTransport<SqsTransport>();
transport.ClientFactory(() =>
{
var amazonSQSConfig = new AmazonSQSConfig()
{
RegionEndpoint = RegionEndpoint.USWest2
};
var client = new AmazonSQSClient(amazonSQSConfig);
var addedTags = new Dictionary<string, string>();
addedTags.Add("Team", "Development");
addedTags.Add("Accounting ID", "number");
var tagQueueRequest = new TagQueueRequest()
{
Tags = addedTags
};
client.TagQueueAsync(tagQueueRequest);
return client;
});
transport.QueueNamePrefix("some-prefix");
endpointConfiguration.Recoverability()
.AddUnrecoverableException<CustomException>();
return endpointConfiguration;
}
Can you provide solution for adding automatically tags during configuring endpoints?
Thank you for any help
The NServiceBus integration with SQS doesn't seem to support configuration of tags at the moment. You'd have to manually create your queues upfront with the appropriate tags or manually add tags to existing queues.
You can raise feature requests for tag support on Particular Software's SQS transport repository here: https://github.com/Particular/NServiceBus.AmazonSQS
I can't manage to get pechkin or tuespechkin to work on my azure site.
Whenever I try to access the site it just hangs with no error message (even with customErrors off). Is there any further setup I'm missing? Everything works perfectly locally.
For a 64 bit app I'm completing the following steps:
Create a new Empty MVC App with Azure, make sure Host in the cloud is selected
Change the app to 64 bit
Log onto the azure portal and upgrade the app to basic hosting and change it to 64 bit
Install the TuesPechkin.Wkhtmltox.Win64 and TuesPechkin nuget packages
Add a singleton class to return the IConverter
public class TuesPechkinConverter
{
private static IConverter converter;
public static IConverter Converter
{
get
{
if (converter == null)
{
converter =
new ThreadSafeConverter(
new PdfToolset(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
}
return converter;
}
}
}
Add a Home controller with the following code in the Index Action:
var document = new HtmlToPdfDocument
{
GlobalSettings =
{
ProduceOutline = true,
DocumentTitle = "Pretty Websites",
PaperSize = PaperKind.A4, // Implicit conversion to PechkinPaperSize
Margins =
{
All = 1.375,
Unit = Unit.Centimeters
}
},
Objects =
{
new ObjectSettings { HtmlText = "<h1>Pretty Websites</h1><p>This might take a bit to convert!</p>" },
new ObjectSettings { PageUrl = "www.google.com" }
}
};
byte[] pdfBuf = TuesPechkinConverter.Converter.Convert(document);
return File(pdfBuf, "application/pdf", "DownloadName.pdf");
As far as i know, you can't make it work in a web app. However, there is a way you can do it: you have to create a cloud service and add a worker role to it. TuesPechkin will be installed in this worker role.
The workflow would be the following: from your cloud web app, you would access the worker role(this thing is possible by configuring the worker role to host Asp.NET Web API 2). The worker role would configure a converter using TuesPechkin and would generate the PDF. We would wrap the pdf in the web api response and send it back. Now, let's do it...
To add a cloud service (suppose you have Azure SDK installed), go to Visual Studio -> right click your solution -> Add new project -> select Cloud node -> Azure Cloud Service -> after you click OK select Worker Role and click OK.
Your cloud service and your worker role are created. Next thing to do is to configure your Worker Role so it can host ASP.NET Web API 2.
This configuration is pretty straightforward, by following this tutorial.
After you have configured your Worker Role to host a web api, you will have to install the TuesPechkin.Wkhtmltox.Win64 and TuesPechkin nuget packages.
Your configuration should now be ready. Now create a controller, in which we will generate the PDF: add a new class in your Worker Role which will extend ApiController:
public class PdfController : ApiController
{
}
Add an action to our controller, which will return an HttpResponseMessage object.
[HttpPost]
public HttpResponseMessage GeneratePDF(PdfViewModel viewModel)
{
}
Here we will configure two ObjectSettings and GlobalSettings objects which will be applied to an HtmlToPdfDocument object.
You now have two options.
You can generate the pdf from html text(maybe you sent the html of your page in the request) or directly by page url.
var document = new HtmlToPdfDocument
{
GlobalSettings =
{
ProduceOutline = true,
DocumentTitle = "Pretty Websites",
PaperSize = PaperKind.A4, // Implicit conversion to PechkinPaperSize
Margins =
{
All = 1.375,
Unit = Unit.Centimeters
}
},
Objects = {
new ObjectSettings { HtmlText = "<h1>Pretty Websites</h1><p>This might take a bit to convert!</p>" },
new ObjectSettings { PageUrl = "www.google.com" }
}
};
A nice thing to now is that when using page url, you can use the ObjectSettings object to post parameters:
var obj = new ObjectSettings();
obj.LoadSettings.PostItems.Add
(
new PostItem()
{
Name = "paramName",
Value = paramValue
}
);
Also, from TuesPechkin documentation the converter should be thread safe and should be kept somewhere static, or as a singleton instance:
IConverter converter =
new ThreadSafeConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDeployment())));
Finally you wrap the pdf in the response content, set the response content type to application/pdf and add the content-disposition header and that's it:
byte[] result = converter.Convert(document);
MemoryStream ms = new MemoryStream(result);
response.StatusCode = HttpStatusCode.OK;
response.Content = new StreamContent(ms);
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
response.Content.Headers.Add("content-disposition", "attachment;filename=myFile.pdf");
return response;
I'm afraid the answer is that it's not possible to get wkhtmltopdf working on Azure.
See this thread.
I am assuming you mean running wkhtmltopdf on Windows Azure Websites.
wkhtmltopdf uses Window's GDI APIs which currently don't work on Azure
Websites.
Tuespechkin supported usage
It supports .NET 2.0+, 32 and 64-bit processes, and IIS-hosted applications.
Azure Websites does not currently support the use of wkhtmltopdf.
Workaround
I ended up creating a Azure Cloud Service, that runs wkhtmltopdf.exe. I send the html to the service, and get a byte[] in return.
The stripe.com API only returns active subscriptions. I want to verify when I delete a subscription.
So this is going to return an error. I am not sure how to code for it.
I would prefer to make this call based on the subscriptionId. Will this cause an exception or will it return an error code?
Retrieving a subscription
var subscriptionService = new StripeSubscriptionService();
StripeSubscription stripeSubscription = subscriptionService.Get(*subscriptionId*);
Another options which is somewhat of a hack is to return all the subscriptions for the given customer and test to see if the subscriptionId was returned.
List all subscriptions for a customer
var subscriptionService = new StripeSubscriptionService();
IEnumerable<StripeSubscription> responses = subscriptionService .List(*customerId*);
foreach( var response in responses )
{
if (response.subscriptionId == subscriptionId)
{
// subscription exists and was not deleted
exit;
}
}
Per their documentation, https://stripe.com/docs/api they have 2 different APIs. You're trying to use the RESTful API, which is for retrieving information on demand.
They also have a WebHooks API, which requires you have an endpoint listening on your site which can accept event notifications. You configure these through your Dashboard with them.
The event type you're looking for specifically is probably the customer.subscription.deleted event, but there's a lot more you can do with them and I'd encourage you to explore all of those Webhooks.
I can't offer a code sample, as I don't use their service.
The strip.net example shows the subscriptionService.Cancel as a methed:
var subscriptionService = new StripeSubscriptionService();
subscriptionService.Cancel(*customerId*, *subscriptionId*);
But you can also use it as a function and it returns the subscription object.
var subscriptionService = new StripeSubscriptionService();
StripeSubscription stripeSubscription = subscriptionService.Cancel(*customerId*, *subscriptionId*);
If (stripeSubscription.Status != "canceled")
{
//subscription not cancelled
// take action
}
Per Stripe API docs:
Returns:
The canceled subscription object. Its subscription status will be set to "canceled" unless you've set at_period_end to true when canceling, in which case the status will remain "active" but the cancel_at_period_end attribute will change to true.One of the fiels is .status , witch is set to canceled.
I'm working with the Nest API, which supports REST Streaming via Firebase. I have REST working, however I cannot get it to stream correctly. This is very important for my app, and REST just isn't effective for what I want to do.
I'm using Hammock for the requests, and here's the code:
public class NestAPI
{
private RestClient client { get; set; }
public NestAPI()
{
this.client = new RestClient();
this.client.Authority = "https://developer-api.nest.com/";
this.client.HasElevatedPermissions = true;
}
public void BeginStreaming()
{
RestRequest request = new RestRequest();
request.AddParameter("auth", App.accessToken);
request.RetryPolicy = new RetryPolicy() { RetryCount = 3 };
//Enables streaming
//request.AddHeader("Accept", "text/event-stream");
//request.StreamOptions = new StreamOptions() { Duration = new TimeSpan(96, 0, 0), ResultsPerCallback = 1 };
this.client.BeginRequest<object>(request, new RestCallback<object>(this.StreamCompletedEvent));
}
private void StreamCompletedEvent(RestRequest request, RestResponse<object> response, object userState)
{
//TO DO: check for errors first
string json = response.Content;
}
public void EndStreaming()
{
this.client.CancelStreaming();
}
}
This code works and does return JSON, however I can't seem to enable streaming. When I uncomment the lines below "Enables streaming", the callback event never fires. It's important to note that authentication is done using the uri parameter, "auth".
Unfortunately, there doesn't seem to be Firebase libraries available, and REST is my only option. I want to know when JSON properties change and want to set different values while streaming.
I'm not familiar with Hammock, but can you make sure that it's set to follow redirects? The streaming endpoint typically issues HTTP 307 to get inform the client of the correct server to connect to.
I've never used Hammock, but looking through source code (briefly) it appears you need to set it up as a streaming request with StreamOptions. Twitter has some open source that uses this here https://github.com/camertron/twitter-windows/blob/master/Source/Twitter/Classes/API/Streaming/UserStream.cs.
The way you have Hammock configured here it's waiting for an entire request to complete before calling your callback. This will (almost) never happen with a streaming request as the server keeps the connection open to push new results.
Good day!
I'm just started with Amazon SES.
I want use this in my asp.net mvc (C#) website.
I download and install AWS Toolkit for Visual Studio, create AWS simple console application.
So, I have sample code that can send email, using AmazonSimpleEmailService client.
PART 1:
using (AmazonSimpleEmailService client = AWSClientFactory.CreateAmazonSimpleEmailServiceClient(RegionEndpoint.USEast1))
{
var sendRequest = new SendEmailRequest
{
Source = senderAddress,
Destination = new Destination { ToAddresses = new List<string> { receiverAddress } },
Message = new Message
{
Subject = new Content("Sample Mail using SES"),
Body = new Body { Text = new Content("Sample message content.") }
}
};
Console.WriteLine("Sending email using AWS SES...");
SendEmailResponse response = client.SendEmail(sendRequest);
Console.WriteLine("The email was sent successfully.");
}
Further, I must configuring Amazon SES Feedback Notifications via Amazon SNS.
I find nice topic with sample code:
PART 3:
http://sesblog.amazon.com/post/TxJE1JNZ6T9JXK/Handling-Bounces-and-Complaints
So, I need make PART 2 where I'll get ReceiveMessageResponse response and send it into PART 3.
I need implement in C# this steps:
Set up the following AWS components to handle bounce notifications:
1. Create an Amazon SQS queue named ses-bounces-queue.
2. Create an Amazon SNS topic named ses-bounces-topic.
3. Configure the Amazon SNS topic to publish to the SQS queue.
4. Configure Amazon SES to publish bounce notifications using ses-bounces-topic to ses-bounces-queue.
I try write it:
// 1. Create an Amazon SQS queue named ses-bounces-queue.
AmazonSQS sqs = AWSClientFactory.CreateAmazonSQSClient(RegionEndpoint.USWest2);
CreateQueueRequest sqsRequest = new CreateQueueRequest();
sqsRequest.QueueName = "ses-bounces-queue";
CreateQueueResponse createQueueResponse = sqs.CreateQueue(sqsRequest);
String myQueueUrl;
myQueueUrl = createQueueResponse.CreateQueueResult.QueueUrl;
// 2. Create an Amazon SNS topic named ses-bounces-topic
AmazonSimpleNotificationService sns = new AmazonSimpleNotificationServiceClient(RegionEndpoint.USWest2);
string topicArn = sns.CreateTopic(new CreateTopicRequest
{
Name = "ses-bounces-topic"
}).CreateTopicResult.TopicArn;
// 3. Configure the Amazon SNS topic to publish to the SQS queue
sns.Subscribe(new SubscribeRequest
{
TopicArn = topicArn,
Protocol = "https",
Endpoint = "ses-bounces-queue"
});
// 4. Configure Amazon SES to publish bounce notifications using ses-bounces-topic to ses-bounces-queue
clientSES.SetIdentityNotificationTopic(XObject);
I'm on the right track?
How I can implement 4 part? How receive XObject?
Thanks!
You are on the right track - for the missing part 4 you need to implement receiving of a message from the Amazon SQS message queue you created in step 1. See my answer to Example of .net application using Amazon SQS for where to find a respective example - it boils down to the following code:
// receive a message
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest();
receiveMessageRequest.QueueUrl = myQueueUrl;
ReceiveMessageResponse receiveMessageResponse = sqs.
ReceiveMessage(receiveMessageRequest);
if (receiveMessageResponse.IsSetReceiveMessageResult())
{
Console.WriteLine("Printing received message.\n");
ReceiveMessageResult receiveMessageResult = receiveMessageResponse.
ReceiveMessageResult;
foreach (Message message in receiveMessageResult.Message)
{
// process the message (see below)
}
}
Within the loop you need to call either ProcessQueuedBounce() or ProcessQueuedComplaint() as illustrated in Handling Bounces and Complaints.
I've recently had to tackle this problem and I couldn't find a good code example on how to handle the SNS bounce notification (as well as topic subscription request) from a .Net website. Here's the Web API method I came up with to handle SNS bounce notifications from Amazon SES.
The code is in VB but any online VB to C# converter should be able to easily get it converted for you.
Imports System.Web.Http
Imports Amazon.SimpleNotificationService
Namespace Controllers
Public Class AmazonController
Inherits ApiController
<HttpPost>
<Route("amazon/bounce-handler")>
Public Function HandleBounce() As IHttpActionResult
Try
Dim msg = Util.Message.ParseMessage(Request.Content.ReadAsStringAsync().Result)
If Not msg.IsMessageSignatureValid Then
Return BadRequest("Invalid Signature!")
End If
If msg.IsSubscriptionType Then
msg.SubscribeToTopic()
Return Ok("Subscribed!")
End If
If msg.IsNotificationType Then
Dim bmsg = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Message)(msg.MessageText)
If bmsg.notificationType = "Bounce" Then
Dim emails = (From e In bmsg.bounce.bouncedRecipients
Select e.emailAddress).Distinct()
If bmsg.bounce.bounceType = "Permanent" Then
For Each e In emails
'this email address is permanantly bounced. don't ever send any mails to this address. remove from list.
Next
Else
For Each e In emails
'this email address is temporarily bounced. don't send any more emails to this for a while. mark in db as temp bounce.
Next
End If
End If
End If
Catch ex As Exception
'log or notify of this error to admin for further investigation
End Try
Return Ok("done...")
End Function
Private Class BouncedRecipient
Public Property emailAddress As String
Public Property status As String
Public Property diagnosticCode As String
Public Property action As String
End Class
Private Class Bounce
Public Property bounceSubType As String
Public Property bounceType As String
Public Property reportingMTA As String
Public Property bouncedRecipients As BouncedRecipient()
Public Property timestamp As DateTime
Public Property feedbackId As String
End Class
Private Class Mail
Public Property timestamp As DateTime
Public Property source As String
Public Property sendingAccountId As String
Public Property messageId As String
Public Property destination As String()
Public Property sourceArn As String
End Class
Private Class Message
Public Property notificationType As String
Public Property bounce As Bounce
Public Property mail As Mail
End Class
End Class
End Namespace
I have the same problem today. I solved the problem by configuring a WebHook (https) in the SNS configuration. On the webserver i process now the events. I have create a nuget package with the logic.
My Code - Nager.AmazonSesNotification
[Route("SesNotification")]
[HttpPost]
public async Task<IActionResult> SesNotificationAsync()
{
var body = string.Empty;
using (var reader = new StreamReader(Request.Body))
{
body = await reader.ReadToEndAsync();
}
var notificationProcessor = new NotificationProcessor();
var result = await notificationProcessor.ProcessNotificationAsync(body);
//Your processing logic...
return StatusCode(StatusCodes.Status200OK);
}