This was a fun one. It was really only a single line of code but I decided to embellish it a bit to make it a bit more useful.
The “task” I set myself was to open a web-page – this blog, in fact – inside AutoCAD as an MDI child. AutoCAD can now host web-pages directly inside its MDI frame – the New Tab Page is a great example of that – and this mechanism can be used for external applications, too. You can also load non-HTML documents into the frame, but it’s quick and easy to use HTML.
The “embellishments” consisted of a couple of things, really…
Firstly, I wanted to check whether the chosen URL was actually loadable (not just valid, but loadable) before having AutoCAD load it. If we don’t do that then we risk a rather inelegant 404 in AutoCAD’s main frame. We check this both by validating the URL and by issuing a “HEAD” request – rather than a full “GET” – as this is significantly cheaper.
Secondly, I wanted to do all this asynchronously, so AutoCAD wouldn’t risk blocking while doing it. As AutoCAD 2015 is using .NET 4.5, it’s safe to assume that async/await is available to applications using the new APIs, so we used that to keep things nice and clean.
Here’s the C# code that loads this blog into AutoCAD:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Net;
using System.Threading.Tasks;
namespace NewDocumentWindow
{
// To check whether a page exists, we can use a HEAD request
// rather than a full GET. Derive a custom client to do that
class HeadClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
var req = base.GetWebRequest(address);
if (req.Method == "GET")
req.Method = "HEAD";
return req;
}
}
public class Commands
{
// Asynchronous helper that checks whether a URL exists
// (i.e. that the URL is valid and can be loaded)
private async static Task<bool> PageExists(string url)
{
// First check whether the URL is valid
Uri uriResult;
if (
!Uri.TryCreate(url, UriKind.Absolute, out uriResult) ||
uriResult.Scheme != Uri.UriSchemeHttp
)
return false;
// Then we try to peform a HEAD request on the page
// (a WebException will be fired if it doesn't exist)
try
{
using(var client = new HeadClient())
{
await client.DownloadStringTaskAsync(url);
}
return true;
}
catch (WebException)
{
return false;
}
}
[CommandMethod("BLOG")]
public async static void OpenBlog()
{
const string url =
"http://blogs.autodesk.com/through-the-interface";
// As we're calling an async function, we need to await
// (and mark the command itself as async)
if (await PageExists(url))
{
// Now that we've validated the URL, we can call the
// new API in AutoCAD 2015 to load our page
Application.DocumentWindowCollection.AddDocumentWindow(
"Kean's blog", new System.Uri(url)
);
}
else
{
// Print a helpful message if the URL wasn't loadable
var doc = Application.DocumentManager.MdiActiveDocument;
var ed = doc.Editor;
ed.WriteMessage(
"\nCould not load url: \"{0}\".", url
);
}
}
}
}
When we run the BLOG command, here’s what we see:
To make this application more interesting, we could use AutoCAD’s JavaScript API to execute commands etc. inside AutoCAD directly from the hosted web-page (just as the New Tab Page does). This opens a host of interesting possibilities from an application development perspective!