Announcement: New open source .NET API (almost)
pe2smugmug
Registered Users Posts: 53 Big grins
Announcing a new .NET library to interface with the 1.2.0 JSON API. Its written in c# and based on the Json.NET library and will probably be released under the GPL (though I am pretty flexible if someone wanted a difference license as well)
Its about 90% complete right now, so I don't have anything to really share with the group, but I am looking for feedback at this stage. Tell me something, anything.
1) Is anyone interested in a library like this or am I wasting my time? Yes there are other libraries out there, but I happen to like open source stuff. For me, it makes debugging, and understanding the code so much easier.
2) What do people want in a library. Right now there exists a nice interface that almost exactly replicates the SmugMug API in a one-to-one manner. I am in the process of working on one that is marginally nicer, in that it keeps track of sessions for you, etc. The third possible interface, would be one that takes the object oriented approach to heart and allows such things as "album.addPicture(newFilename,caption,keywords);", etc.
3) How important is it to get the new 1.2.1 calls? It doesn't take me long to add the new functions, but it does take a while to come up with robust test cases for everything (Go NUnit!)
Please let me know if people are interested, if not I'm probably going to drop it or at least only spend the time implementing the features I want.
-Evan
Its about 90% complete right now, so I don't have anything to really share with the group, but I am looking for feedback at this stage. Tell me something, anything.
1) Is anyone interested in a library like this or am I wasting my time? Yes there are other libraries out there, but I happen to like open source stuff. For me, it makes debugging, and understanding the code so much easier.
2) What do people want in a library. Right now there exists a nice interface that almost exactly replicates the SmugMug API in a one-to-one manner. I am in the process of working on one that is marginally nicer, in that it keeps track of sessions for you, etc. The third possible interface, would be one that takes the object oriented approach to heart and allows such things as "album.addPicture(newFilename,caption,keywords);", etc.
3) How important is it to get the new 1.2.1 calls? It doesn't take me long to add the new functions, but it does take a while to come up with robust test cases for everything (Go NUnit!)
Please let me know if people are interested, if not I'm probably going to drop it or at least only spend the time implementing the features I want.
-Evan
0
Comments
Evan sounds like you are on the right track. Your API sounds very similar to my own done in Java, and the "truely object oriented" approach you mentioned sounds very similar to Anton's API, SmugFig, he's building ontop of my base Java API.
1 suggestion I would make is to consider the Apache 2 license, it's commercial-friendly. GPL will mean your code will ever only be used by other open source projects and is very commercial-unfriendly. If that's the intent (you want it to stay open, always, no matter what) then that's fine, just wanted you to be aware of that.
As far as 1.2.1 goes, the API is like 4x the size of the 1.2.0 API as it adds all the watermarking, community, family, etc. settings that 1.2.0 API didn't have.
I think for most image/sync/browsing/management apps 1.2.0 is sufficient, but if you are literally trying to create an offline version of the SmugMug website, then you would need to use the 1.2.1 APIs to get access to those more robust Pro features.
I'd say release 1.2.0, see how it does, and go from there.
Keep coding!
kallasoft | The "Break It Down" Blog
I’m debating which license to release under. I do like the “copyleft” of the GPL, but if someone wanted to use it for a commercial release I would most likely give it to them under a different license….I’m still debating. As long as I’m the only author I can always re-release under a less restrictive license, but I can’t take it back once it’s released.
Thanks for the encouragement!
What you said about the license is spot on, sounds like you know how you want to handle it.
kallasoft | The "Break It Down" Blog
I think there would be enough interest in your API. I would suggest to do both: Have a lower level one-to-one API and one that is more 'object oriented' on top of the lower level one. This will give people choice which abstraction level they want to use when developing products for Smugmug based on .NET.
When I hear the earth will melt into the sun,
in two billion years,
all I can think is:
"Will that be on a Monday?"
==========================
http://www.streetsofboston.com
http://blog.antonspaans.com
So I'll second the Apache 2 license suggestion (or some other equivalently non-viral license) - oh, yeah, and as BugBlatter says, hosting it on CodePlex is definitely the way to go (Codeplex has a good list of non-viral licenses that you can choose from when you are configuring your project).
-Don
Regardless of whatever license it ends up officially released as, (and as a note to any future readers of this thread) contact me if you are thinking of not using it or developing another library because of a license issue, I can’t really imagine a case where I wouldn’t let you use it.
Moving on to more enjoyable stuff, the project currently lives on the sourceforge site that I have from pe2smugmug and I don’t see a reason for moving. There is code available for download in the SVN repository if people want to take a look, but there is still plenty of stuff broken and untested. Hopefully I will find some time this weekend to put together some kind of alpha release that has the low level API (similar to the Java API) completed.
I'm completely confused. You are aware that the Apache 2 license (and the openBSD license, and the MIT license, and the 40 or so other licenses listed here http://www.opensource.org/licenses/category) are open source licenses aren't you? Just about every linux web server on the net runs Apache. Apache is an open source project. It uses the Apache 2 license. Odds are that you are viewing this posting in Firefox. Firefox is an open source project. It uses the Mozilla Public License (another great non-viral open source license).
Your offer to allow others to use the library under other licenses sounds great, but as soon as anyone fixes a bug in your code and uploads it to sourceforge, you can't do that because it's no longer your code. You can't change the license without having the permission of every contributor. If five people fix bugs, you need permission from all five of them in order to let anyone use the library under another license. It's only "your" code and only "your" project as long as you are the sole author. But the whole goal of open source is to encourage others to share in the authorship. Which is why the choice of license is so incredibly important and why that choice has to be made right at the beginning of the project.
Multiple people who are likely contributors and users of your library are telling you "GPL is not compatible with my involvement in an open source project". It's totally your choice, but if you are interested in fostering a community around the library that you are starting, listening to that community seems like a great place to start
-Don
How important is it for the library to be thread-safe?
My currnet handling of errors is to deal with them is to return a null or some kind of special value, instead of throwing an exception. You can then call something like getLastError() to find out what went wrong. So while the calls are safe, I can only save most recent error which could be a problem in a multi-threaded application...
Okay, I think I just answered my own question.
I'm going to go with throwing exceptions and get rid of the whole getLastError() thing. I'm stuck in c instead of c# .
Well, in that case, let me know if anyone disagrees and thinks lastError is better.
I tend to avoid designs that *force* clients of the API into programming a certain way, and it sounds like your current design would force me to design a certain way (with the getLastError call).
I don't know how exceptions are in C#, but in Java you have a choice between checked and unchecked exceptions, so I don't know if you have a subsequent decision to make at that level as well to make clients have an easier time using your API.
kallasoft | The "Break It Down" Blog
I would stay away from constructs like 'getLastError()'.
- How would one know when to call 'getLastError()'?
- The 'getLastError()' is then used to obtain the reason for a failure (the reason why an invalid value was returned earlier).
- All in all, just using exceptions is safer. I would opt for checked exceptions, exceptions that the user of your API has to deal with in some form or fashion. The exception can contain the failure (the fact that it is being thrown) and the reason for the failure (type of exception, some other data stored in the exception).
However, don't use exceptions for every little thing. If it is not truly an error-condition, don't use exceptions. E.g. missing values can be easily represented with returning null, undefined or "", or something. If a value was just missing in a valid response (e.g. valid response from a smugmug-function), no error took place. Using an exception to take note of this fact is overkill. But if the missing value was caused by a failed response, an exception may be in order when the caller wants to retrieve it.Some other method returned an invalid value?
If so, then one needs an if-statement. Choosing to ignore the invalid value can be dangerous.
Threading and modifiable objects.... many ways to go about it.
To make your library thread-safe, you can either implement locks (synchronized calls, semaphores, locks, etc) or you can require users of your API to create individual instances for each thread (no instance is shared by several threads, no shared use of modifiable static/global variables).
In my SmugFig API, i use checked exceptions for true anticipated failures from the system (e.g. network failures, invalid responses from smugmug, etc); i return null for undefined attribute-values (no exceptions); i use unchecked exceptions for incorrect user-input (the caller provided an incorrect input-parameter).
For thread-safety i use a combination of both 'individual instances for each thread' and 'locking'. My API lets users create objects from a prototype. Each prototype must be newly instantiated and should not be used by more than one thread. But as soon as an object is created, it can be shared by multiple threads (makes caching of these objects easier) and the objects can be locked for modification.
When I hear the earth will melt into the sun,
in two billion years,
all I can think is:
"Will that be on a Monday?"
==========================
http://www.streetsofboston.com
http://blog.antonspaans.com
Its been a while since I've programmed in Java, but in c# you can choose to wrap a function in a try/catch block (you can of course choose to do nothing in your catch block). If an exception is not caught in one of these blocks, it will eventually propigate up and result in a run-time error. So in this case, I kind of am forcing users of the API to program in a certain way, but this is very common for .NET and the built in libraries.
The getLastError is probably less standard for a .NET language, but is more likely to allow the user to ignore an error (which while offering the programmer more flexibility, is probably not a good thing).
Right now, I'm thinking about error primarily as a smugmug call returning stat!=ok. Returning an empty set might be perfectly valid for something like subcategories.get if none are defined... yes?
As for network problems, etc. Those are currently handled by the built in calls, and get passed allong as a lower level exception.... hadn't put too much thought into that just yet.
Regarding thread safety, right now, other then my lastError problem, all of my calls are thread safe, though I am still working on the low level functions, no real object oriented goodness.
typically empty sets return error code 15 (empty set).
SmugMug API Developer
My Photos
Then, when the API implements 'getFileName()', instead of throwing an exception, i think it would be better to just return null/undefined: The response from smugmug was valid, no problems there; it saves the caller of the API a lot of code (i can imagine code-snippets with a lot of getSomeAttribute() calls in a row; if they all need to be surrounded by try-catch blocks.... ouch).
I just need to make sure to document the API:
- SmugmugObject.getSomeAttribute() always returns a proper value, or 'null' if:
- The attribute is part of a 'heavy' response. The caller needs to do a 'getInfo()' first on the object to obtain the value for 'SomeAttribute'. Or:
- The attribute is not accessible for the logged-in user.
- Make sure that there are methods available so that the caller can determine which of the two reasons causes the return value to be null/undefined.
E.gor
When I hear the earth will melt into the sun,
in two billion years,
all I can think is:
"Will that be on a Monday?"
==========================
http://www.streetsofboston.com
http://blog.antonspaans.com
I wish it did not return an error-code! An empty set is not wrong or incorrect. It is just an empty set, a very valid answer to the json/rest/etc/-request: "You don't have any images in your album".
Is there no way to just return a response without any images/albums and such, without using an error-code?
When I hear the earth will melt into the sun,
in two billion years,
all I can think is:
"Will that be on a Monday?"
==========================
http://www.streetsofboston.com
http://blog.antonspaans.com
So I've been ignoring the Release Early, Relese Often motto, so I decided to put together what I have and release it.
You can download a zip with the .dll file to start playing with it here:
https://sourceforge.net/project/showfiles.php?group_id=196700&package_id=255051
For source code access, point your svn client to:
https://pe2smugblog.svn.sourceforge.net/svnroot/pe2smugblog/trunk/SmugMug.NET
There should be plenty of InteliSense comments to help you get started, but I will try and post some examples shortly.
At the moment there are two ways to access the library.
1) Via the SmugMug.libSmugMug.SmugMugApi interface - This is pretty much a one-to-one mapping of the smugmug api, and the user is required to keep track of their own sessionID. 1) Via the SmugMug.libSmugMug.SmugMug interface - This one is not yet complete, but it tries to hide some of the background stuff from the user, like sessionID's. Eventually, this is the interface I would like to promote usage of.
Same example Well, let me know what people think, what features I should add first and what bugs need to be addressed first...
Oh yeah, I think I have settled on releasing under the LGPL, which should offer a nice balance. This library itself must remain open source under the LGPL, however you can use the library in either an open source or a comercial closed-source application. That should make people happy.
Cheers
So you've cleared that hurdle, onto Release #2!
kallasoft | The "Break It Down" Blog
I would be happy to commit some dev and test time to this API. In fact I am currently changing my windows live writer plugin to use this API instead of the XML-RPC one I was using before.
One quick suggestion I would make is the read up on the C# naming guidelines http://msdn2.microsoft.com/en-us/library/xzf533w0(VS.71).aspx. The current naming scheme you are using if more Java centric and while that is fine, it does look odd in a .NET program and it makes the API a bit harder to use.
New release (version 1.0.1) is now available from sourceforge. (https://sourceforge.net/project/showfiles.php?group_id=196700&package_id=255051)
Primary change involves adding a LoginForm for easy Login (also handles saving account information in the registry).
Also combined Json.NET into the project, so the library is now a single .dll for ease of use.
I got a little distracted on this release, focusing on the LoginForm and handling saved accounts. The plan is to go back to focusing on core features and to create a small "Demo" project to help people figure out how to use the library.
So the both interfaces are pretty much complete for the logged in user. I am now going to switch to working on getting the accessor methods to work by NickName, and using password protected albums, etc.
As an added bonus, I have included the latest copy of the Demo project in the zip file. While not a very robust piece of code, it shows how to use logs of the basic features of the library.
Feedback always appreciated.
Another new release, Version 1.0.3. Things seem quite stable at this point, if you notice problems are any issues, let me know so I can fix them.
This is a pretty signficant update, so PLEASE read the changelog. Most important, I changed the name of the primary class from SmugMug.libSmugMug.SmugMug to SmugMug.libSmugMug.SM. The original name was foollish, because I had named the class the same as the namespace causing all kinds of problems. I am also facing another dilema with my choice of name for the Image class, which conflics with the built in System.Drawing.Image class; not quite certain what I should do, but I am open to suggestions.
This fixes a problem with past releases when adjusting boolean values for album/gallery settings. Sorry about that.
I took a look at the upload code, and I don't really see an easy way to accept filestreams for uploading. My upload function is based on the System.Net.WebClient class, which only offers upload methods for a file or for an array of bytes. My suggestion would be to write out the file to a temporary file, then upload that file. Just remember that the file permissions on your webserver might be different then on your development machine, so you need to make sure you have write access to your temporary folder.
-Evan
Evan,
I will try saving the file to a temporary folder on my web server, this means then that it will take more time to complete the upload - from a user's browser to my webserver and then from my webserver to smugmug. Is there a better/faster way to do this?
Thanks!
Sherwin
That being said, I don't see why you couldn't download and upload at the same time. There are limitations of course; to be in spec with uploading files to smugmug, two of the headers required are the MD5sum of the file (for error checking) allong with the size of the file being uploaded, I don't know if most webbrowsers send these headers before they start uploading a file, which is the only way to be able to compute them without the full file. Now this isn't a show stoper, smugmug is forgiving and will accept uploads without those two headers, but I don't know how well it can handle error checking without them.
Regarding implementing such a solution.... I'm not really a c# expert, so I don't know if DataStreams can handle being written to and read from at the same time. Again, I'm even less knowledgeable regarding ASP.NET, so I don't know how you would handle the threading issue (if such an issue exists?)....
Hm... another thought, double check that your code is actually getting called while the upload is still happening, not after the upload finishes. I only ask, because I'm pretty certain that with apache & php, the php script doesn't get called until AFTER the upload is finished. If the same thing is true in IIS & .NET, then the delay of writing the file to disk should be quite small relative to the time it takes to upload/download the file.
Sorry for the ramblings, let me know about when the code is being executed and how important speed is, and we can work from there.
Also, any ASP.NET guru's out there, please jump in and help me out
-Evan
I will have to look if I HTTP Post work for me to upload photos to Smugmug, I had a hard time making it work months ago...but with your library, I should be able to utilize to make it work. I'll keep you posted.
Thanks!