News Blog - Browsing BlogSvc
-
BlogSvc.net is now AtomSite
We have changed the name of BlogSvc.net to AtomSite starting with the next version. The benefits of this change are:
- This app is more than just a blog engine, it is a full CMS
- Atom syndication format and AtomPub are the core of this app
- Just as Atom is extensible, this app is extensible
- The app is great for building and managing a website
- Easier to spell, no abbreviation
We hope you agree that AtomSite is a great name for this Atom based website publishing system.
-
OpenID and Auth Updates
The next release will contain full support for OpenID for both normal logins and comments. OpenID can be enabled or disabled per workspace. When enabled, it adds the new custom OpenID javascript selector to the login page.
It also adds support to the comment section. Clicking on Login will popup the OpenID javascript selector.
The authentication system was simplified in the process of adding OpenID. There is a new authentication module called OpenIdAuthenticationModule that can be used along side the existing authentication system built into ASP.NET. Now, authentication is handled consistently across all modes: Basic, WSSE, OpenId, and Forms. The authentication service was no longer needed so it has been removed.
The User domain object now implements IIdentity and is available through HttpContext.User.Identity or Thread.CurrentPrincipal.Identity.
Users in the UserRepository can have multiple id's to support multiple OpenID's for each user.
The AppService domain object was also updated to reference these user id's instead of containing actual AtomPerson domain objects. These updates were propagated to the authorization service. Also, the AtomPerson domain object was updated with an id property so a reference can be made back to the user repository.
Also, the authorization was cleaned up across the AtomPub and Annotation services. The role actions "Annotate", "ApproveEntryOrMedia", and "ApproveAnnotation", are now used in place of AnnotationApprovalMode, EntryApprovalMode, and AnnotatationMode. To control who can annotate and approve, just customize the role matrix. Finally, there is a new setting called AnnotationsOn to allow you to disable annotations regardless of the role matrix.
See the Annotations page for more information.
-
Plug-Ins and Dynamic Controllers
Update: The content of this post is out of date. The concept of plug-ins has since been expanded to support more scenarios, including widgets, plug-ins, and controllers.
The next release contains new support for plug-ins as described in previous posts. Plug-ins are supported using the Dependency Injection framework StructureMap.
The following types are pluggable:
Service Level Plug-ins Default Type Collection Plug-ins Default Type ILogService NLogService IRouteService AtomPubRouteService IController N/A IAtomPubService AtomPubService IUserRepository FileUserRepository IAnnotateService AnnotateService IAppServiceRepository FileAppServiceRepository ICleanContentService XhtmlCleanContentService IAtomEntryRepository FileAtomEntryRepository IMediaRepository FileMediaRepository IAppCategoriesRepository FileAppCategoriesRepository IAuthorizeService ServiceAuthorizeService The Service Level plug-ins can all be controlled using the <StructureMap> configuration section in the web.config file.
The following example shows how to set properties on the blog collection to use the Blog Plug-in:
The RouteService registers routes on the collections first. Then it registers the default routes. Special care must be taken when registering routes so they occur in the correct order. Also, plug-in routes should take care to use the collection constraint so that routes are properly overridden only on collections using the RouteService plug-in.
Controllers are dynamically instantiated using the StructureMap ObjectFactory. Therefore, plug-ins can provide new routes and handle them with new controllers. Currently, new routes are limited to collection plugins that fire the RegisterRoutes event. This will be extended in the future to support routes outside of collections for things such as widgets.
I am currently flushing out the Widget story and I'm leaning towards a combination of techniques using PartialRequests and Modularity. If you have any suggestions for widget support, please leave a comment below.
-
Update to ASP.NET MVC RC1
I've checked in the code to update BlogSvc to ASP.NET MVC RC1 Refresh. There were only minor updates to get things workings and the overall process only took around 10 minutes. However, the readme notes on the configuration are misleading. The release notes tell you to update the pages section to look like:
<pages
validateRequest="false"
pageParserFilterType = " System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35 "
pageBaseType = " System.Web.Mvc.ViewPage, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35 "
userControlBaseType = " System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35 " >
This is not necessaryas you'll notice when creating a new MVC project that three bolded lines are not included. When I added the lines to my config it caused errors on my hosting provider.Update: yes, the readme notes are very misleading. These lines should actually be added to the web.config file in the "Views" directory. I added these lines to web.config file in the themes folder.
-
Routing Updates
I just checked in a large refactor on the routing system to allow for collection plug ins to register their own routes. All routing implements the IRouteRegistrar interface that has a RegisterRoutes method. The BaseRouteRegistrar abstract base class contains some useful implementation and logic that can be reused for plug-in routing.
AtomPubRouteRegistrar the implementation for all the default routes. The default routes will always get registered after plug-in routes. Remember, order is important because routing always takes the first match.
Each collection can plug-in their own routing with a constraint that will ensure the routes are only active for the collection/collections that registered the routes.
Also, I added some extensions on top of UrlHelper that calls the RouteService class which has support for SSL routes and absolute routes. We lost automatic deep routes on threaded annotations. However, there's baked in support for "dated" entries. We are using named routes so that makes it really easy to select which route you want when generating the URL.
-
Refactor for Extensibility
Update: Some of the content of this post is outdated. The whole plug-in system was greatly revised to support better extensibility scenarios.
One the features we are working towards in 2009 are Collection Plug-ins. The goal is to utilize the extensibility of AtomPub so that it is possible to layer any kind of collection on top of it. This is being done by Google, Microsoft, and many others for providing things such as calendars, contacts, photo galleries, etc.
By using a combination of ASP.NET MVC, dependency injection, and extensibility points, we hope to allow any type of collection to be stored on top of AtomPub. To accomplish that, I'm moving towards a design where all collections are built according to IAtomPubService interface. This interface describes the base functionality needed by any collection. The methods in gray are extensions to the AtomPub standard which I consider a core need for managing any collection. I'm have considered splitting this interface into a couple smaller pieces.
public interface IAtomPubService { AppService GetService(); AppService UpdateService(AppService service); AtomFeed GetCollectionFeed(Id collectionId, int pageIndex); AtomFeed GetFeed(Id collectionId, int pageIndex, int pageSize); AtomFeed GetFeedByAuthor(Id collectionId, string authorName, int pageIndex, int pageSize); AtomFeed GetFeedByContributor(Id collectionId, string contributorName, int pageIndex, int pageSize); AtomFeed GetFeedByPerson(Id collectionId, string personName, int pageIndex, int pageSize); AtomFeed GetFeedByDate(Id collectionId, DateTime startDate, DateTime endDate, int pageIndex, int pageSize); AtomFeed GetFeedByCategory(Id collectionId, string term, Uri scheme, int pageIndex, int pageSize); AtomFeed GetFeedBySearch(Id collectionId, string term, int pageIndex, int pageSize); AppCategories GetCategories(Id collectionId, Uri scheme); AtomEntry GetEntry(Id entryId); Stream GetMedia(Id entryId, out string contentType); AtomEntry CreateEntry(Id collectionId, AtomEntry entry, string slug); AtomEntry CreateMedia(Id collectionId, Stream stream, string slug, string contentType); event EntryEventHandler EntryCreated; AtomEntry UpdateEntry(Id entryId, AtomEntry entry, string slug); AtomEntry UpdateMedia(Id entryId, Stream stream, string contentType); event EntryEventHandler EntryUpdated; void DeleteEntry(Id entryId); void DeleteMedia(Id entryId); event EntryEventHandler EntryDeleted; string GetEntryEtag(Id entryId); string GetMediaEtag(Id entryId, out string contentType); AtomEntry Annotate(Id entryId, AtomEntry entry, string slug); AtomEntry MediaAnnotate(Id entryId, Stream stream, string slug, string contentType); event EntryEventHandler Annotation; AtomFeed GetAnnotations(Id id, bool deep, int pageIndex, int pageSize); }We will provide a base implementation (AtomPubService) to this interface that contains only logic required by the AtomPub standard. Collection plug-ins can either extend this base implementation or create a new collection service from scratch against the IAtomPubService interface. For example, a blog collection may extend the AtomPubService to include blog related methods such as ApproveEntry or SendTrackback.
There are some additional methods that may need to be added to support the core infrastructure. For example, a collection should be responsible for registering routes to the resources within that collection. Also, a collection should be responsible for choosing the repository, authorization, and other services based on user configuration.
Hopefully, through the magic of an IoC framework, controllers and views can be selected dynamically when I install a new collection plug-in. For example, I want to create a collection plug-in that will allow me to create generic web pages. Most of the logic I need already exists in the Blog Collection but I have a few changes to add support for sub-page annotations. I just extend the BlogService class and override a couple functions. I create a couple new views and controller actions which hit my new PageService class and I'm done. I'm still working through this scenario, so let me know if you have any comments on the design.
-
What’s Ahead in 2009
BlogService has come a long way in the past four months. We went from being a small WCF web service all the way to a solid content management system. This year we will continue to move forward with great new features.
Read More
-
Wizard Release 0.8
The eighth release of BlogSvc includes a new setup wizard. Also, this release contains the following new or improved features:
- Setup wizard will test your installation on your web server
- Setup wizard will modify your service.config and users.config
- New green theme called "Settings" (see right)
- All entries are cleansed from html to xhtml
- Comments allow html only from a whitelist of tags
- Authorized comments can use any tags
- New support for wlwmanifest.xml
- Entries can now be split in live writer or with <!--more--> comment
- Collection page now only shows first part of post when split
- New ExtendedEntriesOn setting for each collection which alters wlwmanifest.xml
- Feeds now only show first part of post when ExtendedEntriesOn
- Updates to jQuery rater plugin based on community feedback
- Updated Search to use render partial
- Updated views and partials to use strongly typed models
- BaseController and BaseModel greatly increase view potential
- Updated all existing entries to Xhtml
- Remove emails from annotation feeds (to prevent spam)
Visit the release page on codeplex to download.
-
New Setup Wizard
The next release will make setting up BlogSvc.net very simple. You won't even need to manually edit the config files as they are done as part of the wizard.
Loading…Wizard Steps
The wizard currently has 3 steps:
Read More
-
Extended Entries Support
I added extended content support for people who like to only show part of the post on their feed and listing pages.
There is a new setting on each collection called "ExtendedEntriesOn" which will alter the wlwmanifest.xml depending on the setting. Please note that setting this value to false will not disallow the <!--more--> tag. However, a theme designer may alter the display/layout of the theme based on this setting.
The collection page and simple entry partial were modified to have a "Read More" link whenever there is extended content.
For feeds, if ExtendedEntriesOn=True then each entry in the feed will not show the extended content (it will only show the content before the split).
Live Writer has built in support for splitting entries as seen in the picture to the right.