Jekyll2019-10-07T19:53:24+00:00blog.automatedapi.com/feed.xmlAutomatedApi BlogMaking APIs easy and fast for as many devs as possible...and blogging about it.Progress Report: October is gonna be YUUGE2019-10-07T21:01:28+00:002019-10-07T21:01:28+00:00blog.automatedapi.com/product/update/2019/10/07/progress-update<h1 id="the-latest-and-greatest">The Latest and Greatest</h1>
<p>Unfortunately the content plans for September are little behind schedule. Content is always a problem for me, but I think I’m getting better at making myself actually post things. Since last I wrote here, I did manage to piece together a new sample app that uses all but one of the HTTP methods that AutomatedApi.com supports. In doing so, I have expanded a previous bit of code into a full fledged library, which will be open source and freely available to help people save time with integrations built on this platform.</p>
<p>Come to think of it, that Http client library is actually useful far beyond AutomatedApi, so I hope that can be of use in a broad category. Wouldn’t want to pigeon hole a thing that could be useful with so many projects.</p>
<p>Another thing I realized when building the second sample app (it’s simple inventory management btw) is that the implementation code becomes a bit repetitive. I hate that, so I’ve added downloadable code, dlls, and potentially nuget libraries to the list of features I’d like to add support for over the course of the next year.</p>
<h2 id="got-a-big-ol-bump-in-traffic">Got a big ol’ bump in traffic</h2>
<p>AutomatedApi is growing as I expected, and I’m happy to notice that it was featured on <a href="https://dzone.com/articles/5-upcoming-tools-for-software-developers-that-will">DZone</a>. I had zero expectation of that but am glad that other people see something useful in what I’m building. Signups have been very encouraging, and we’re approaching triple digits in terms of user reservations. That should jump a bit more once the product pushes through the closed beta phase and I can offer some free usage with a free account.</p>
<h2 id="features-in-the-pipe">Features in the Pipe</h2>
<p>October is planned to be big for the product. In the course of this month I intend to add the following:</p>
<ol>
<li>logging with visibility for users, i.e. a preliminary dashboard</li>
<li>secured apis by default, this will be achieved via API keys which can be added or revoked by users via their portals</li>
<li>rate limiting and usage measures, I’ve not really tried to hide the fact that rate limiting and usage are currently not measured. In fact until I get that in place, all signed up users could basically build and create to their hearts content free of charge.</li>
</ol>
<p>I’ll be interested to see if this causes a bump in throughput to the site, and to see what kind of problems an increased load might introduce.</p>
<p>Cheers Folks!</p>The Latest and Greatest Unfortunately the content plans for September are little behind schedule. Content is always a problem for me, but I think I’m getting better at making myself actually post things. Since last I wrote here, I did manage to piece together a new sample app that uses all but one of the HTTP methods that AutomatedApi.com supports. In doing so, I have expanded a previous bit of code into a full fledged library, which will be open source and freely available to help people save time with integrations built on this platform.Building a Daily Log Application with Automated API2019-09-14T21:01:28+00:002019-09-14T21:01:28+00:00blog.automatedapi.com/app/example/2019/09/14/building-a-webapp<p>So, I built a thing. Part of building any product like AutomatedApi is actually taking the thing for a spin. I was inspired by things like <a href="https://750words.com/">750words</a> recently and I thought I’d give something like that a whirl. What I didn’t want to do was manage a database and build an api and then have to manage both deployments in some attempt to be all ‘microservice-y’. Fair warning, the app itself is rough, my purpose was to get something built fairly quickly so I haven’t cleaned up error pages or failed login stuff, what you get when navigating to this POC demo is without second and third pass refinements. Enjoy.</p>
<h2 id="the-plan">The Plan</h2>
<p>The app I had in mind should be a short build ending in a fully functional diary/logging application that I could post up somewhere and have people actually interact with, even potentially sign up to use for as long as it remains online. I present to you the <a href="https://DailyLogging.automatedapi.com">AutomatedApi Daily Logger</a>. It’s on a different login domain, so testing would require an account to be created there. I’m sure I’ll reuse that db for identity on other demo apps, but I promise not to ever look at that db directly…no one actually wants to manage more dbs, that’s kinda the point of AutomatedApi.</p>
<h2 id="the-layout">The Layout</h2>
<p>I Rolled up a simple layout that i picked up from Pixelarity some time back and spun it into an ASP.NET Core web application with run of the mill identity management as suggested in .NET core documentation and tutorials. Essentially all of this could be hacked together using tutorials in something like 30 minutes to an hour. To keep things as simple as possible (it’s all designed to one page), if you’re not logged in - you’re asked to log in, and if you are - you should be able to make an entry and see that entry on the lower part of the screen.</p>
<p>I wanted the entries to be put together in a timeline, they’ve always interested me but I’ve never actually built any. As such, each entry will be comprised of only a few properties:</p>
<ol>
<li>a timestamp</li>
<li>a text entry</li>
<li>a link to a user id</li>
</ol>
<h2 id="the-build">The Build</h2>
<p>To achieve that, I submitted this to the Automated API Portal when creating a new API.</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"openapi"</span><span class="p">:</span><span class="w"> </span><span class="s2">"3.0.1"</span><span class="p">,</span><span class="w">
</span><span class="nl">"info"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">""</span><span class="p">,</span><span class="w">
</span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"paths"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">},</span><span class="w">
</span><span class="nl">"components"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"schemas"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"UserDailyLog"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"UserId"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"LogEntry"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"string"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"EntryDate"</span><span class="p">:{</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="s2">"datetime"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>I knew this would generate a service with a 4 properties (including the autogenerated id), so I then built some data transfer objects with with the following shapes as suggested by the documentation for POSTing new entries and GETting collections of them with a simple filter on UserId.</p>
<h3 id="the-internal-model">The Internal Model</h3>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">public</span> <span class="k">class</span> <span class="nc">UserDailyLog</span>
<span class="p">{</span>
<span class="k">public</span> <span class="n">Guid</span> <span class="n">UserDailyLogId</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">UserId</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">LogEntry</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">DateTime</span> <span class="n">EntryDate</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="dtos-and-collection-models">DTOs and Collection Models</h3>
<p>The first one just inherits from my internal one, it was built with that intent and why not leverage something if we know it has the same shape.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">public</span> <span class="k">class</span> <span class="nc">UserDailyLogDTO</span><span class="p">:</span> <span class="n">UserDailyLog</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">UserDailyLogForCreationDTO</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">UserId</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">LogEntry</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">DateTime</span> <span class="n">EntryDate</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>And for collections, I needed an object for the metadata so I could eventually build some paging mechanism.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">public</span> <span class="k">class</span> <span class="nc">AutomatedApiMetadata</span>
<span class="p">{</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">TotalCount</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">PageSize</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">CurrentPage</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">int</span> <span class="n">TotalPages</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">PreviousPageLink</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="kt">string</span> <span class="n">NextPageLink</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">UserDailyLogDtoCollection</span>
<span class="p">{</span>
<span class="k">public</span> <span class="n">List</span><span class="p"><</span><span class="n">UserDailyLogDTO</span><span class="p">></span> <span class="n">UserDailyLogs</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="k">public</span> <span class="n">AutomatedApiMetadata</span> <span class="n">PaginationMetadata</span> <span class="p">{</span> <span class="k">get</span><span class="p">;</span> <span class="k">set</span><span class="p">;</span> <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Nothing too complicated. I don’t want to build updates in, so I only built to use the POST method and the GET for collections.
I already had some http client logic built in at that point using a utility I’ll be sharing separately on this blog, so all I had to do at that point was hook up the Urls that would be needed and make sure it worked in the razor pages I’d put already together. And BONUS, by the time I’d finished writing these classes, the service was ready and available through the automatedapi gateway, so I was ready to roll.</p>
<p>For the getter I ended up assembling this for the getter url.</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">opUri</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="s">$"https://gateway.automatedapi.com/AutomatedApi/UserDailyLogs?searchQuery=</span><span class="p">{</span><span class="n">User</span><span class="p">.</span><span class="nf">FindFirst</span><span class="p">(</span><span class="n">ClaimTypes</span><span class="p">.</span><span class="n">NameIdentifier</span><span class="p">).</span><span class="n">Value</span><span class="p">}</span><span class="s">"</span><span class="p">);</span>
</code></pre></div></div>
<p>and this for the POST url</p>
<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">var</span> <span class="n">opUri</span> <span class="p">=</span> <span class="k">new</span> <span class="nf">Uri</span><span class="p">(</span><span class="s">$"https://gateway.automatedapi.com/AutomatedApi/UserDailyLogs"</span><span class="p">);</span>
</code></pre></div></div>
<p>The end result worked out pretty nicely.
Total time to live: 2 hours, but only because I found and fixed a bug in the core product while I was building this out.</p>
<h2 id="a-couple-notes">A couple notes</h2>
<ol>
<li>I realize that I’m using a userid in a general search context. This introduces some risk but only if someone stumbles onto the same GUID and includes it in their log entry, extremely unlikely and this is only a toy app.</li>
<li>Having built this, I think I see a way to build a better search term that maps by id. I’ll add that to the list for October release.</li>
<li>Someone better shoot me an email to remind me to post that http client code to a github repo, eventually I’ll slam it into a nuget package too, I’d really like to just be able to download that with a click, but for now, copying into new projects isn’t so bad.</li>
</ol>
<p>Cheers folks!</p>So, I built a thing. Part of building any product like AutomatedApi is actually taking the thing for a spin. I was inspired by things like 750words recently and I thought I’d give something like that a whirl. What I didn’t want to do was manage a database and build an api and then have to manage both deployments in some attempt to be all ‘microservice-y’. Fair warning, the app itself is rough, my purpose was to get something built fairly quickly so I haven’t cleaned up error pages or failed login stuff, what you get when navigating to this POC demo is without second and third pass refinements. Enjoy.Progress Report and Updates to Come2019-09-03T20:30:00+00:002019-09-03T20:30:00+00:00blog.automatedapi.com/product/update/2019/09/03/progress-update-and-things-to-come<p>I’ve been heartened by what reception this product has had. Granted, said reception is small, but that was my intent with the beta launch and I have confidence that it only grows from here.</p>
<h2 id="updates">Updates</h2>
<p>Since last I posted here there have been several platform updates.</p>
<ol>
<li>The gateway service should now behave in a more stable way.</li>
<li>I’ve added support for deleting customer APIs. This is a logical delete, so they are recoverable. Send me an email and I can make something work.</li>
<li>Documentation with some sample calls has been written</li>
<li>I stood up some other backend related items</li>
</ol>
<h2 id="soon-to-come">Soon To Come</h2>
<p>HUGE updates coming to the generator this month.</p>
<p>One of the goals of the platform is to provide fully REST compliant services. What currently exists is rough but generally functional RESTish generated services. I am hard at work with a rewrite of the backend that better aligns HTTP verbs with the data structures and calls. Once complete, generated services will be fully <a href="https://blog.restcase.com/4-maturity-levels-of-rest-api-design/">Level 2</a> compliant with the Richardson REST Maturity Model. This will include support for both json and xml acceptance types, include paging for calls on collections, filtering and searching of collections, data shaping with url parameters, and come with more complete HTML status codes.</p>
<p>This will also come with more model definitions and UI on the portal to make those models obvious to users. I hope to deliver a SwaggerUI implementation but that may slide into October.</p>
<p>This is a major refactor and extension but lays groundwork that will be integral to the overall value I hope to provide.</p>
<h3 id="known-issues-experienced-by-beta-users">Known Issues Experienced by Beta Users</h3>
<p>There have been several users logging in to try out some api creation, and a couple of failures as well. The most prominent is actually a failure where a bug in the parsing dlls do not recognize a property mapping in the Open API spec. This specifically refers to the a ref within a schema definition. These APIs will fail to generate for now, but that type of nested foreign key relation isn’t something best suited to this application. That is a feature on the roadmap though, so look forward to that in the coming month or two.</p>
<p>Another issue I’ve seen in the logs is attempts to use an enum in a schema definition. While formally supported the spec, it was selectively deferred in this iteration of the code generator on our backend. However, enums would just be mapped to ints at the lowest implementation level, so you could treat it as an int in your applications, and map that to an int in the schema definition for now. Not ideal, but it would be functional. Mapping to an enum and enforcing it on our backend in the current generator would imply another table and a maintenance service exposed, which reduces flexibility on the code side of the equation.</p>I’ve been heartened by what reception this product has had. Granted, said reception is small, but that was my intent with the beta launch and I have confidence that it only grows from here.We’re LIVE! Welcome to closed beta2019-08-20T19:51:28+00:002019-08-20T19:51:28+00:00blog.automatedapi.com/product/update/2019/08/20/welcome-to-automatedapi<p>Well, soft launched at the very least.</p>
<p>As of yesterday, AutomatedApi.com is up and running with user registration, login, api creation, and api access.
There are a few details yet before it’s completely useful but this represents huge progress.</p>
<p>The purpose of this blog will be mostly technical in nature. It’s a way for automated api development to be done at least partially in public.
I have a large number of updates and extensions planned for the coming weeks and will be notifying here frequently.</p>
<p>Latest Update:</p>
<ul>
<li>Hit go on the site</li>
<li>Published a rudimentary Documentation site <a href="docs.automatedapi.com">here</a></li>
<li>published a rudimentary blog right here so you can see it</li>
</ul>
<p>Some notes on current function.
1 There is a bug in the parse which causes errors in component schemas that contain ‘ref’ entries, avoid them for now
2 when inputing an Open API spec, you should include an ‘info’, ‘paths’, and ‘components’ (with schemas). Most of the spec can be empty, but the service specifically uses the schema definitions to build, so it is where your models should be defined.
3 I understand that is now notice on screen for how an api, once created will be generated, HTTP calls should be sent to proxy.automatedapi.com, but I intend to have sample links on the portal page to make that as easy to see as possible.</p>
<p>Cheers</p>Well, soft launched at the very least.