Monday 9 March 2015

Azure API Management - APIM, consuming a SOAP WCF service over HTTP


Update 26/March/20 - In the intervening years Azure APIM has come a long way - it's now quite common to see customers of APIM facading SOAP webservices - using both Liquid and XSLT to transform legacy webservices to a more modern RESTful experience. 
Please do checkout the Azure APIM docs.

***

At the time of writing:

I've been looking at the excellent API-Management feature of Azure .. I understand this functionality has come about through an acquisition (Apiphany). 

I think Azure APIM could offer some great benefits. 

After becoming familiar with the product through the documentation I was still a little confused about how or in fact whether a WCF-SOAP service was supported as the back-end service. The APIM documentation focuses very much on a REST based example back-end service.

(Note: I assume the readers familiarity with APIM and a previous walk through of the documented examples).

To add to my confusion one of the feedback comments for the APIM product appeared to suggest SOAP was not in fact YET supported: feedback-for-api-management-suggestions 

However logic suggests it should work, a SOAP envelope submission over HTTP is via a POST, there are really only three prerequisites 

1. Valid SOAP envelope XML which contains an XML body which the target Web service will be able to de-serialize. 
2. A matching SOAPAction request header
3. A Content-Type header of "text/xml"

One further consideration is how the consumer obtains the contract for the service. It's an implementation detail, but it's possible to define an http and/or https endpoint from which the consumer of the service can acquire the service definition in the form of a WSDL. From .net v4.5 onward a "singleWSDL" option is supported which I believe to be generally preferable and better for interop.

There were a couple of goals:

1. Firstly I wanted to look at options around surfacing some existing internally facing WCF implemented basic-http (SOAP) services for the future

2. I wanted policy and the end user experience to centre around both endpoint and operation.

In my test I published a simple test WCF service to a public facing server, I didn't add security to this service - wishing to keep it simple initially - but the service was restricted to TLS from the front end load balancer out. So any test would be over https.

The URL for my test back-end service was something like this

https://ourdomain.com/helloworld/service1.svc?singlewsdl

The service had two methods:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    string HelloWorldOperation1(string value1, int value2, bool value3);
 
    [OperationContract]
    CompositeType HelloWorldOperation2(CompositeType composite);
}

(Composite type wrapped the same basic types passed in operation 1 as params)

After creating an API instance on Azure within our account I added some users, a product and a new API!

1. Publisher Portal, API Management, APIs: Settings

The settings of the API were very basic - I did try and import the WSDL definition from file, out of curiosity and after playing with the encoding to get that right (it didn't like the initial file we copied out of Visual Studio). However quickly got an error around the WSDL not being understood. 
It could have been me, so it might work, I didn't take more than a couple of minutes trying. Certainly at the time of writing WADL and SWAGGER were the two radio option buttons to describe the definition contents type.

Web API Name = "Hello World" 
Description =
Connection = Directly (in a real scenario I'd explore VPN between APIM and back-end, which is beyond this post)

Web Service URLhttps://ourdomain.com/helloworld/service1.svc
Web API URL Suffix = service1Endpoint
Https = [ticked]

This was the resulting Web API URL

https://[ourazuredomain]helloworld.azure-api.net/service1Endpoint

2. Publisher Portal, API Management, APIs: Operations

Here's the interesting bit, APIM really doesn't do much until you add at least one operation and doesn't seem to surface at all right now if you publish an API without any (which is logical).

This is the bit I got stuck with, what to put in the operation section for a SOAP endpoint method?

What I began by doing was adding a single POST method to cover all endpoint methods, thus:

Http Verb = "POST" (I want to post my soap envelope)
Url Template = "/"
Rewrite URL tempate = ""
Display Name = "All operations"

But, I want to be in a position to add a POST operation to the API for each endpoint method, and this endpoint encapsulates ALL the methods, it's the SOAPAction at the back-end service which determines which method gets invoked on the endpoint and then the request XML within the SOAP body must match!

So I went back to the Web Service URL from step 1 and changed it to this:

Web Service URL = https://ourdomain.com/helloworld

(note I've lopped off the "/service1.svc" endpoint part)

Then I went back and edited my API method to look like this:-

Http Verb = "POST" 
Url Template = "/operation1"
Rewrite URL tempate = "/service1.svc"
Display Name = "Operation 1"

The key point here is that we now specify a URL segment to represent the method but we ALWAYS rewrite it to the service endpoint.

The reason for doing this is so that I can specify distinct operations.

But now I've got a further problem - there's nothing that can enforce the fact that I need the right payload for this operation to go to the right method....Yet...

Next I added an additional operation in for the second web service method, identical to that above except for the URL Template ("/operation2") and the Display name "Operation 2".

Finally I added a third method, a GET this time, to allow my consumers a chance to see the WSDL

Http Verb = "GET" 
Url Template = "/GetWsdl"
Rewrite URL tempate = "/service1.svc?wsdl" 
Display Name = "Get WSDL"

(Note: My test server was net4.0 otherwise it'd have been ?singleWsdl)
The important point is that my GET to the exposed URL segment "/GetWsdl" will always return the wsdl for this endpoint as it's re-rewritten as "/service1.svc?wsdl". I.e. with the wsdl URL query param.

Finally, one more step before I publish; need a way to associate the SOAP header to the correct operation - and one more thing I need to ensure I'm sending and receiving with a content type of "text/xml". And not "text/plain".

3. Publisher Portal, API Management, Policies: Policy Scope

I added a policy using the wizard for each of the endpoint operations defined in the steps above, the XML ended up looking like this:

GetWsdl
  


<policies>
 <inbound>
  <set-header exists-action="override" name="content-type">
   <value>text/xml</value>
  </set-header>
  <base></base>
  <rewrite-uri template="/service1.svc?wsdl">
 </rewrite-uri></inbound>
 <outbound>
  <set-header exists-action="override" name="content-type">
   <value>text/xml</value>
  </set-header>
  <base></base>
 </outbound>
</policies>





Operation1
  


<policies>
 <inbound>
  <set-header exists-action="override" name="content-type">
   <value>text/xml</value>
  </set-header>
  <set-header exists-action="override" name="SOAPAction">
   <value>http://tempuri.org/IService1/HelloWorldOperation1</value>
  </set-header>
  <base></base>
  <rewrite-uri template="/service1.svc">
 </rewrite-uri></inbound>
 <outbound>
  <set-header exists-action="override" name="content-type">
   <value>text/xml</value>
  </set-header>
  <base></base>
 </outbound>
</policies>




Operation2
  

<policies>
 <inbound>
  <base></base>
  <set-header exists-action="override" name="content-type">
   <value>text/xml</value>
  </set-header>
  <set-header exists-action="override" name="SOAPAction">
   <value>http://tempuri.org/IService1/HelloWorldOperation2</value>
  </set-header>
  <rewrite-uri template="/service1.svc">
 </rewrite-uri></inbound>
 <outbound>
  <set-header exists-action="override" name="content-type">
   <value>text/xml</value>
  </set-header>
  <base></base>
 </outbound>
</policies>




Given the fact the policies are hierarchical I could have optimized this by moving the content type header up a level.

The next most important part is the SOAPAction for the POST operations.

This ensures the right action goes with the right operation. There's nothing stopping the end user from sending a different action and request content but note the policy is set to OVERRIDE whatever the users sending which means they'd get an error if they sent the wrong payload to the wrong URL.

Clearly there's one quite big problem with all of this: When the user imports the WSDL into a .net application it's going to want to do so under a single endpoint - whereas APIM will want to a distinct URL per method. So there's a mismatch.

One approach could be to define the operations with the differentiator as a query string argument (of the SOAPAction name) instead of the URL segment, here's how operation1 might look like

Http Verb = "POST" 
Url Template = "/?op=HelloWorldOperation1"
Rewrite URL tempate = "/service1.svc"
Display Name = "Operation 1"


Later on that would be called, along with the subscription key instead of:

https://[ourazuresomain]helloworld.azure-api.net/service1Endpoint/operation1/?subscription-key=[ourkey]

It would be


https://[ourazuredomain]helloworld.azure-api.net/service1Endpoint/?op=HelloWorldOperation1&subscription-key=[ourkey]


Now the caller only has to manage the one URL in their web.config (let's assume they're using .net for now).

However this raises yet another point, which is how does the customer ensure that the subscription key gets added in the first place so the APIM façade allows the call through... 

We could ditch the subscription key, it's optional within APIM, but it's one of the things I'd want to use.

As it turns out, the subscription key doesn't have to be passed as a query string param, it can instead be passed via a request header.
The subscription key request header is "ocp-apim-subscription-key".

This might make more sense for a consuming customer, who could configure a set outbound header against their caller/client app to be attached for outgoing requests to our API.

In Summary
The exercise has proved we can relatively easily façade a wcf http SOAP service through APIM and go onto craft a neat developer portal experience, but, it doesn't feel quite right yet. The APIM is currently REST centric and requires a unique URL per operation. This is at odds with SOAP which is a single URL and utilises a SOAP Action to route to the correct operation for the contract the endpoint URL represents. 
The steps detailed above put the onus on the APIM façade consumer to modify the outbound call from client to service [façade] and that doesn't feel right. Also posted a comment here: feedback-azure-api-management-suggestions-soap-support



69 comments:

Online.Tom said...

Thanks man, this looks very useful. Currently trying to map some WCF endpoints to Azure APIM, I'll see if I can't use this as a guideline :)

Cheers!

AVS said...

You can use API Management solution that supports both REST and SOAP natively. For example, Sentinet product from Nevatech is 100% built on the Microsoft platform with full support for SOAP, REST and SOAP to REST transformations, http://www.nevatech.com.
You can also connect it to Azure APIM if you want to add Azure APIM features.

hammad said...

I must say you have very interesting content here. Your
website should go viral.
Bitdefender
Office 2017
Corel
Corel

Unknown said...

I really appreciate information shared above. It’s of great help. If someone want to learn Online (Virtual) instructor lead live training in Windows foundation communication, kindly contact us http://www.maxmunus.com/contact
MaxMunus Offer World Class Virtual Instructor led training on Windows foundation communication. We have industry expert trainer. We provide Training Material and Software Support. MaxMunus has successfully conducted 100000+ trainings in India, USA, UK, Australlia, Switzerland, Qatar, Saudi Arabia, Bangladesh, Bahrain and UAE etc.
For Demo Contact us:
Name : Arunkumar U
Email : arun@maxmunus.com
Skype id: training_maxmunus
Contact No.-+91-9738507310
Company Website –http://www.maxmunus.com



Unknown said...

Hi admin, i went through article. As we all know, .net is most popular programming language and it offer huge career prospects for talented professionals. It’s totally awesome, keep on updating your blog with such awesome information.
DOT NET Training in ChennaiDOT NET Course in Chennai

Unknown said...

My partner and I stumbled over here different website and thought I might as well check things out. I like what I see so now I’m following you. Look forward to checking out your web page repeatedly.

Hadoop Training in Chennai

Unknown said...

Nice blog! very informative keep update your information Azure Online Training

Sunshine Eco Cleaning said...

Thanks for sharing informative article. Our Website Sunshine Eco Cleaning Services is developed on .Net Framework and it works fine without any security flaws.

Unknown said...

Thanks for sharing information with clear explanation. This is really awesome to understand.

Thanks,
QTP Training in Chennai | QTP Course in Chennai

Unknown said...


Wow it is really wonderful and awesome thus it is very much useful for me to understand many concepts and helped me a lot. it is really explainable very well and i got more information from your blog.

rpa training in Chennai | rpa training in pune

rpa online training | rpa training in bangalore

Mounika said...

I have been meaning to write something like this on my website and you have given me an idea. Cheers.
python training in Bangalore
python training in pune
python online training
python training in chennai

LENIN said...

A very nice guide. I will definitely follow these tips. Thank you for sharing such a detailed article. I am learning a lot from you.

Data science course in tambaram | Data Science course in anna nagar
Data Science course in chennai | Data science course in Bangalore
Data Science course in marathahalli | Data Science course in btm

cynthiawilliams said...

Thanks for sharing this pretty post, it was good and helpful. Share more like this.
ccna Training institute in Chennai
ccna institute in Chennai
DevOps Training in Chennai
AWS Training in Chennai
Angularjs Training in Chennai
RPA Training in Chennai

prabha said...

Really great post, I simply unearthed your site and needed to say that I have truly appreciated perusing your blog entries.

angularjs Training in btm

angularjs Training in electronic-city

angularjs online Training

angularjs Training in marathahalli

angularjs interview questions and answers

srinithya said...

Informative post, thanks for sharing.
Blue Prism Training Chennai
Blue Prism Training Institute in Chennai
Blue Prism course in Chennai
Blue prism course
Blue Prism Training in Velachery
Blue Prism Training in Tambaram

Azure DevOps said...

Thanks for sharing the useful Information.
Amazon Web Services Online Training

Sakthi Murugan said...

Your article increases the curiosity to learn more about this topic. Keep sharing your information regularly for future reference.
Selenium Training in Chennai
Selenium Training
iOS Training in Chennai
Digital Marketing Training in Chennai
Hadoop Training Chennai
Hadoop Training in Chennai
Big Data Training in Chennai

Anbarasan14 said...

Thanks for sharing these effective tips. It was very helpful for me.

Best IELTS Class in Chennai
Best IELTS Courses in Chennai
IELTS Course in Chennai
IELTS Class near Chennai
IELTS Center in Mumbai
IELTS Training in Mumbai
Best IELTS Coaching Classes in Mumbai

Aruna Ram said...

Wonderful article!!! It is very useful for improve my skills. This blog makes me to learn new thinks. Thanks for your content.
CCNA Training in Bangalore
CCNA Course in Bangalore
CCNA Institute in Bangalore
CCNA Training in Tambaram
CCNA Training in Chennai Velachery
CCNA Training in Tnagar

gowthunan said...

I’m using the same blog platform like yours, and I’m having difficulty finding one? Thanks a lot.
industrial safety courses in chennai

LindaJasmine said...


Your post is very attractive. Your style of writing is very unique.
Primavera Training in Chennai
Primavera Course in Chennai
Primavera Software Training in Chennai
Best Primavera Training in Chennai
Primavera p6 Training in Chennai
Primavera Coaching in Chennai
Primavera Course

yuvarani said...

This information is impressive. I am inspired with your post writing style & how continuously you describe this topic. Eagerly waiting for your new blog keep doing more.
Aws Training Institutes in Bangalore
Aws Certification Training in Bangalore
Aws Training Center in Bangalore
Best Institute For Java Training In Bangalore
Java J2ee Courses In Bangalore

Unknown said...

Thanks first of all for the useful info.
the idea in this article is quite different and innovative please update more.
Python Training in Vadapalani
Python Training in Amjikarai
best python course in bangalore
best python training bangalore

Unknown said...

Nice post. By reading your blog, I get inspired .. Thank you for posting.

Informatica Training in Chennai
Informatica Training Center Chennai
Informatica Training Institute in Chennai
Best Informatica Training in Chennai
Informatica course in Chennai
Informatica Training center in Chennai
Informatica Training
Learn Informatica

Aruna Ram said...

You have provided a nice post. Do share more ideas regularly. I am waiting for your more updates...
PHP Training Center in Bangalore
PHP Institutes in Bangalore
PHP Course in Perambur
PHP Training in Nolambur
PHP Training in Tnagar
PHP Course in Nungambakkam
PHP Training in Navalur
PHP Course in Kelambakkam

Harish said...

It is an informative post. Your blog has some useful knowledge.

Vmware Learning
Best VMware Training in Chennai
Vmware Training center in Chennai
Best VMware Training Center in Chennai
VMware Vsphere Training
Vmware Training center in Adyar
Best VMware Training in Tambaram
Vmware Training center in Velachery

Vicky Ram said...

Nice post. I learned some new information. Thanks for sharing.

Education
Technology

mercyroy said...

I really thank you for your innovative post.I have never read a creative ideas like your posts.here after i will follow your posts which is very much help for my career.
AngularJS Training in Nolambur
AngularJS Certification Training in T nagar
Angularjs Training in Bangalore
angularjs training center in bangalore

LindaJasmine said...

Amazing Blog. The liked your way of writing. It is easy to understand. Waiting for your next post.
Node JS Training in Chennai
Node JS Course in Chennai
Node JS Advanced Training
Node JS Training Institute in chennai
Node JS Training Institutes in chennai
Node JS Course
Informatica Training in Chennai
Informatica Training center Chennai
Informatica Training Institute in Chennai

VenuBharath2010@gmail.com said...

I liked your way of writing. Waiting for your future posts. Thanks for Sharing.
IELTS coaching in Chennai
IELTS Training in Chennai
IELTS coaching centre in Chennai
Best IELTS coaching in Chennai
IELTS classes in Chennai
Tableau Training in Chennai
Tableau Course in Chennai
Informatica Training chennai

VenuBharath2010@gmail.com said...


Amazing write-up. The content is very interesting, waiting for your future write-u
Html5 Training in Chennai
Html5 Courses in Chennai
Html5 Training
Html5 Course
Html5 Training Course
Drupal Training in Chennai
Drupal Certification Training
Drupal 8 Training
Drupal 7 Training

Joe said...

Wonderful Post. The content is very much thought provoking. Thanks for sharing.
Ethical Hacking Course in Chennai
Hacking Course in Chennai
Hacking Course
Learn Ethical Hacking
Spoken English Classes in Chennai
Best Spoken English Classes in Chennai

sunshineprofe said...

I must say this blog loads a lot quicker than most. Can you suggest a good internet hosting provider at a reasonable price?
fire and safety course in chennai

Joe said...

You are an amazing writer. The content is extra-ordinary. Looking for such a masterpiece. Thanks for sharing.
IoT courses in Chennai
IoT Courses
IoT Training
IoT certification
IoT Training in Porur
IoT Training in Adyar
IoT Training in Anna Nagar

Joe said...

Great work. It shows your in-depth knowledge. Your article is very thought-provoking.
Node JS Training in Chennai
Node JS Course in Chennai
Node JS Training Institutes in chennai
Node JS Course
Node JS Training in T Nagar
Node JS Training in Anna Nagar
Node JS Training in Porur
Node JS Training in Adyar

Priyanka said...

Attend The Python Training in Bangalore From ExcelR. Practical Python Training in Bangalore Sessions With Assured Placement Support From Experienced Faculty. ExcelR Offers The Python Training in Bangalore.
Python Training in Bangalore

Trigent Infotech said...

Thanks for all your hard work it is much appreciated...
Trigent Infotech mission is to enhancing the business growth of our customers. We deliver high-quality software's that create value for our clients around the world. We always try to improve the quality of our products by exploring innovative ideas.

Unknown said...


I like viewing web sites which comprehend the price of delivering the excellent useful resource Python training in pune free of charge. I truly adored reading your posting. Thank you!

Unknown said...

Hi, I do believe this is a great website. I stumbledupon it ;) I will come back once again since i have book-marked it Gadgets. Money and freedom is the greatest way to change, may you be rich and continue to guide other people.

hami said...

Click here to Cloud tech.

nizam said...

Good post. Thank you for valuable information.

BEST ANGULAR JS TRAINING IN CHENNAI WITH PLACEMENT

https://www.acte.in/angular-js-training-in-chennai
https://www.acte.in/angular-js-training-in-annanagar
https://www.acte.in/angular-js-training-in-omr
https://www.acte.in/angular-js-training-in-porur
https://www.acte.in/angular-js-training-in-tambaram
https://www.acte.in/angular-js-training-in-velachery

nizam said...

You are providing an excellent article.
AngularJS training in chennai | AngularJS training in anna nagar | AngularJS training in omr | AngularJS training in porur | AngularJS training in tambaram | AngularJS training in velachery


divya said...

Are you still facing problem, while working on QuickBooks Payroll Accounting Software? Have,
you yet not received, a reliable technical support team? If that’s the case, you have landed on thansk
Ai & Artificial Intelligence Course in Chennai
PHP Training in Chennai
Ethical Hacking Course in Chennai Blue Prism Training in Chennai
UiPath Training in Chennai

vivekvedha said...

"Nice Article you have made here, It’s an informative and interesting post, keep it up.

Digital Marketing Training Course in Chennai | Digital Marketing Training Course in Anna Nagar | Digital Marketing Training Course in OMR | Digital Marketing Training Course in Porur | Digital Marketing Training Course in Tambaram | Digital Marketing Training Course in Velachery
"

ramesh said...

The post is really beautiful. concepts are very neatly represented.

Azure Training in Chennai | Certification | Azure Online Training Course | Azure Training in Bangalore | Certification | Azure Online Training Course | Azure Training in Hyderabad | Certification | Azure Online Training Course | Azure Training in Pune | Certification | Azure Online Training Course | Azure Training | microsoft azure certification | Azure Online Training Course

Revathi said...

This is very good content you share on this blog. it's very informative and provide me future related information.thanks!!!


android training in chennai

android online training in chennai

android training in bangalore

android training in hyderabad

android Training in coimbatore

android training

android online training

vijay said...

It would have been the happiest moment for you,I mean if we have been waiting for something to happen and when it happens we forgot all hard work and wait for getting that happened.
Salesforce Training in Chennai

Salesforce Online Training in Chennai

Salesforce Training in Bangalore

Salesforce Training in Hyderabad

Salesforce training in ameerpet

Salesforce Training in Pune

Salesforce Online Training

Salesforce Training

shiva said...

Your blog is really helpful.

Cyber Security Training Course in Chennai | Certification | Cyber Security Online Training Course | Ethical Hacking Training Course in Chennai | Certification | Ethical Hacking Online Training Course |
CCNA Training Course in Chennai | Certification | CCNA Online Training Course | RPA Robotic Process Automation Training Course in Chennai | Certification | RPA Training Course Chennai | SEO Training in Chennai | Certification | SEO Online Training Course

saketh321 said...

It's late finding this act. At least, it's a thing to be familiar with that there are such events exist. I agree with your Blog and I will be back to inspect it more in the future so please keep up your act. ExcelR Machine Learning Course

ganesh said...

Thanks for one marvelous posting! I enjoyed reading it; you are a great author. I will make sure to bookmark your blog and may come back someday. I want to encourage that you continue your great posts.
Angular js Training in Chennai

Angular js Training in Velachery

Angular js Training in Tambaram

Angular js Training in Porur

Angular js Training in Omr

Angular js Training in Annanagar

sahasrit said...

Thank you for taking the time and sharing this information with us. It was indeed very helpful and insightful while being straight forward and to the point.
amazon web services aws training in chennai

microsoft azure course in chennai

workday course in chennai

android course in chennai

ios course in chennai

Pushba said...

Great work. It shows your in-depth knowledge. Your article is very thought-provoking.
IELTS Coaching in chennai

German Classes in Chennai

GRE Coaching Classes in Chennai

TOEFL Coaching in Chennai

Spoken english classes in chennai | Communication training

Rosemarie Cozart said...

very creative! Learned a lot from your post. Nice to read the above article, really explains everything in detail, the article is very interesting and effective. Voice recording is an art. Voice is a complicated thing. You can spend years studying sound and still not know how to produce sound on it. I had read an article related to this about How to Do Voice Over Like a Pro: The Complete Guide and this article helped me a lot. If you need some information about Voice Over, then this article can prove to be suitable for you.

Unknown said...

This is very informative and interesting for those who are interested in blogging field. Really very happy to say, your post is very interesting to read.
I have post which you can read to learn more about Spacebar Counter. After spending couple of hours on research I have come to this article Importance of spacebar speed which you can happy read.

Anna Buckley said...

The writing of this blog is unique, as well as the topic. A Twitter chat is an excellent way to network, learn business strategies from peers, and engage in meaningful conversations about shared interests. Twitter helps us all connect with a much larger audience than we would otherwise be able to. But how can we chat with them? If you do not know anything about this topic, this article will be very helpful. For more details visit here how to participate in a twitter chat. Thank you so much

Unknown said...

I finally found a great post here. I will get back here. I just added your blog to my bookmark sites.
I am sharing a very genuine post to read where you can get to know about Spacebar Speed Test. Please refer article spacebar counter

Unknown said...

Interesting post. I'm wondering about this issue, so thanks for posting. Pretty much a post. Very good and useful post.
This is a website where you can learn more Spacebartest. Here you can find all the tips and tricks related to keyboard. So please visit the site‌ to read its latest post cps test about cps test.

casinositeking 카지노사이트 said...

Hey man, .This was an excellent page for such a hard subject to talk about. I look forward to reading many more great posts like these. Thanks Feel free to visit my website; 온라인카지노사이트

casinositeking 카지노사이트 said...

I get pleasure from, cause I found just what I used to be having a look for. You’ve ended my four day long hunt! God Bless you man. Have a nice day. Feel free to visit my website; 카지노사이트링크

casinositeking 카지노사이트 said...

Good web site! I truly love how it is simple on my eyes and the data are well written. I am wondering how I might be notified when a new post has been made. Feel free to visit my website; 바카라사이트닷컴

Gregory Carney said...

Thanks for sharing your article. Very good information. Everyone can benefit from it, including me. The information is useful to anyone who uses it. Here keyboard tester you will find the solution to your keyboard problem that is not working.

Reshma said...

Awesome blog. Thanks for sharing this blog. Keep update like this...
Android Training in Bangalore
Android Classes in Pune

MeriFain said...

Thank you for sharing with us this wonderful article. Click Counter should be familiar with the game.This lets you know how fast you can click. You can also speed up your tapping speed again. To learn more, click here click speed test

John said...

I like this post and I love to write articles click the link below to read the blog.
Flaunt Yellow Kurta Sets

David Perry said...

Silverbell is a 3D Architectural Visualization and Rendering Company in Delhi, India specialising in creating high quality 3D services like architectural visualisation, Product Visualization, 3d Interior Designer Rendering visualisations for Architects, interior designers,3D Interior Designer ,corporate sector, and the Real estate industry and more.

3D Product Visualization
3D Architectural Rendering

Pavithra Devi said...

This post is so interactive and informative.keep update more information...
Data Science course in Tambaram
Data Science course in Chennai

affordable interior designer said...

Thank you for sharing your awesome and valuable article this is the best blog for the students they can also learn.
https://lookobeauty.com/best-interior-designer-in-gurgaon/

Anna Buckley said...

We are pleased to inform you that your post is excellent after reading it. I hope you continue to publish such content. Check out this profile for Monitor refresh rate. can measure the refresh rate of your monitor. Read this then. We hope you'll find it beneficial.

Unknown said...

I am impressed by the information that you have on this blog. Thank you for sharing. The Canuckle Word Game's multiplayer mode encourages players to connect with others and can foster a sense of community among players. Go through this profile to know more about Canuckle Game.