Article: The making of Blogo.NET »
FERDY CHRISTANT - APR 4, 2008 (12:51:01 PM)
This article explains into detail how I developed Blogo.NET, which is an n-tiered internet blog application based upon .NET 3.5. The article really is many articles into one, as it explains the full process of development, including architecture, database design/access (LINQ), UI design, security and much more.
Due to its size (43 pages), the article is provided as a downloadable PDF:
The making of Blogo.NET v1.00 - PDF (2,186 KB)
If you chose to link to this article, please link to this page, not the download link. You can provide feedback and comments below, I welcome everyone to do this. Thanks everyone for taking the time to read the article!



Comments: 23
Reviews: 4
Average rating:
Highest rating: 5
Lowest rating: 5
COMMENT: MARK BARTON

APR 10, 2008 - 07:47:48
A great piece of work.
Do you see many changes to get your reference architecture to work with a winforms application? «
COMMENT: FERDY
APR 10, 2008 - 03:30:09 PM
Thank you. In fact no, due to this architecture, you only have to change the View layer in order to make it work with Winforms, everything else is completely decoupled. «
COMMENT: ROMAN KOPAC

APR 11, 2008 - 16:37:53
COMMENT: FERDY
APR 11, 2008 - 09:45:19 PM
You're welcome, looks like I just saved you some money. I hope you like the article. «
COMMENT: NUWANDA
MAY 1, 2008 - 03:27:33
I've shed a few tears recently trying to figure out a solid .net architecture that looks good from A-Z. I'm no expert but your architecture looks really maintainable, scalable, readable, fast and each layer is friendly to use. I'm thinking about alot of things after reading(skimmed through some parts, saving the full read untill a long flight later in the week :) your article, as I say'd I'm just a beginner so hopefully you will bear with me if my questions are silly. I'm wondering about the Linq to Sql part, is that inhibiting you in any way? compared to using ado.net in the data layer, and the linq objects, always transforming them to custom objects how is that effecting performance, wouldt it be faster with using a datareader? And using dumb classes, that couples the data access layer to the domain model alot, agen passing a .net framework class(datareader) from the DAL to the BLL would maybe be better? Also with this architecture, with the GetList() method for example....you need one gridview and one ObjectDataSource and one page for each *Manager class, to display all your lists. If you have 100 lists this might be bad practice? Is there a way(inheritance/polimorphism/factory pattern) to be able to only use one gridview and one ODS in one page to display all the lists. If you know from a value on the page which *Manager GetList() method to use.
Since this is not a support forum I've said more then anough already :) Thank you agen for this excelent article.
Nuwanda «
COMMENT: FERDY
MAY 8, 2008 - 03:39:14 PM
Thanks for your compliments and detailed response. Hereby a few answers from my side:
- concerning the conversion of LINQ object to custom data objects: There are different ways to do this, for example you can directly bind from controls to LINQ classes, or you can define an intermediate layer like I did. The advantage of an intermediate layer of objects is that you have a neutral layer, the disadvantage is that it requires some manual steps to keep them in sync. There is no single best practice, you have to make this choice yourself.
- I have not tested the performance difference between data readers and LINQ data access, but in many modern applications, the difference is probably so tiny that nobody would notice.
- It is true that in my architecture the Data Access layer has to know about the dumb Business Objects, but the same applies if we would not have these dumb objects. In that case, the business layer would talk directly to the LINQ classes, and would have to know about those too. What if the data access layer changes? «
COMMENT: DONNA
JUN 3, 2008 - 01:26:25 PM
question - yes, there seems to be much work in coding what's "proper" behind the scenes. With the addition of LINQ and the capability of VS to generate a dbml file, much work is alleviated from the DAL.
However, as you pointed out, there is still much to be done in the BAL - creating the "dumb" objects and their respective managers. It appears most of this code is redundant and similar all the way through the entire database.
My question is this... now that I have a good representation of how to architect an ASP.NET app (or other), what can I do to reduce my development time at least as far as the "plumbing" code?
You mentioned "generating" my code. Might you have insight on a recommended code generator? I've seen on the web, but am not familiar with CODESMITH, MYGENERATION, ENTITYSPACES (?), etc.
Please let me know what you can about these and others including which direction you would recommend for me. I would welcome your input!
Thanks so much for this and especially your article. What a generous and helpful contribution to the community. It's very inspiring!
Donna «
COMMENT: FERDY
JUN 3, 2008 - 03:26:37 PM
Thanks for the compliments, I'm glad you liked the article. As for code generators, I have little experience in the .NET world. At work we are using DSL technology, which is extremely powerful, but a bit hard to comprehend. SQLMetal is a more light weight option that is more related to LINQ. I suggest Googling around a bit, as I am not an expert on this matter. «
COMMENT: DONNA

JUN 4, 2008 - 08:01:33 AM
Again, great material; thanks so much for sharing!
Donna «
COMMENT: DONNA
JUN 4, 2008 - 08:31:17 AM
In your article, you mention that the business rules would be placed in the "manager" classes. Got it.
What about any global variables like for storing info for user sessions? How do you recommend establishing / managing global vars, specifically for individual user sessions (e.g. session variables, etc.)?
Thanks for any input!
Donna «
COMMENT: DONNA
JUN 26, 2008 - 07:51:52 AM
You may be aware, but I found a glitch in Blogo.NET. The "author" name does not get filled-in when anonymous users enter a "comment".
The line is in BlogEntry.aspx.cs, line 27. It checks if the user is authenticated and sets to it if so, but then it erroneously blanks the user's name if it's not authenticated.
I corrected as:
if (User.Identity.IsAuthenticated)
CommentName.Text = User.Identity.Name;
Again, if you were already aware, please ignore. Otherwise, I hope this helps everyone!
Donna «
COMMENT: FERDY
JUN 26, 2008 - 02:43:25 PM
COMMENT: DONNA
JUN 27, 2008 - 10:17:58 PM
There's a required field in the comments section for the visitor to enter his/her name.
Any person making a comment will either be:
1) an admin person logged-in, or
2) a non-admin person (or an admin person not logged-in which is the same).
In either case, the value that is in the textbox for the name field when the comment is saved is not used. Instead, the value is either pulled from the admin record (for case #1), or is blanked-out (in case #2). Both cases ignore/overwrite what was entered.
Does this make better sense?
When I stated "bug" I meant of the "logic" type, not "code". But like I said, I might be missing something. Is this the behavior you intended? If so, could you elaborate? «
COMMENT: DONNA
JUN 27, 2008 - 10:56:19 PM
Off of the last topic, in your "making of" PDF, on page 10, there's a link to "example queries" for LINQ. The PDF doesn't have the link as clickable. Can you share the URL to that?
Thanks for any assistance,
Donna «
COMMENT: FERDY
JUN 30, 2008 - 08:02:46 AM
The link for the LINQ examples is:
http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx «
COMMENT: DONNA
JUL 1, 2008 - 03:03:23 AM
Out of the "box", it runs quite smoothly, but it doesn't take long to discover that the "name" field isn't getting retained (saved to DB) during user comments unless it's an admin person and even then, it ignores what's typed/edited and uses the entry from the admin table.
Let me be clear though -- I LOVE the project you did. I think it's great and I truly appreciate people like you out there taking the time to create such a thorough tool, which I know takes valuable time, and then offer it free to the community. It deserves much respect.
Got the link -- thanks so much!
Donna «
COMMENT: JEFF

DEC 14, 2008 - 02:48:29 AM
Laters,
Jeff
«
COMMENT: TIM ERFLE
FEB 5, 2009 - 05:05:31 PM
I implemented Imar Spaanjaars' architecture for my last project, but followed your design closer on this project due to the fact you used LINQ. I've spent quite a bit of time going through your write up and code. It takes balls that clank to put your source code out for scrutinizing. Ok, now for my question:
So blog_tags in a mapping object and not a business object. That makes sense in your architecture to not have a business object for each mapping table in the database. Due to the fact that its not a business object, its parent B.O. (in this case BlogEntry) must handle the creating and deletion of the mapping objects.
So my question is on update of the parent object you blow away the mapping object and recreate it. So in your example, if you update the title of a blog entry your must recreate the mapping for no apparent reason. Is there a good reason for this? Seems like for a high traffic site you could eat through mapping ID's in the db. «
COMMENT: FERDY
FEB 5, 2009 - 07:17:28 PM
Thank you for taking the time to go through the article and source code, as always, every kind of feedback is welcome here.
Is is a good question you have. It is a design decision, really. Deleting and recreating the mappings for each edit/save is the easiest way to implement. A more complex way is to do it, is to go through all existing mappings for the entry and then compare them to the tags in the form. Next, add the new ones, and/or delete the ones that were removed. In both cases you will be touching the database quite a lot, so I went for the easiest solution.
I do not suspect this choice to become a problem for a blog application, SQL can handle millions if not billions of entries. A high traffic site has little to do with this, as the creation of ids is related to edits, not traffic. Should this design choice really be a problem though, feel free to improve the source code
«
COMMENT: TIM
MAR 24, 2009 - 10:25:46 PM
After implementing this architecture, I ran into one issue which wasn't easy to track down. Thought I would comment here in case someone else has the same problem. The root of the problem is that the connection is created within each static class and shared within its methods. If too many connections are open its possible to receive the error "Executereader requires an open and available connection". One solution would be to open a connection in each method wrapped in a using statement to insure the DataContext was properly disposed. Like:
public static int Count()
{
using (BlogoMapDataContext db = new BlogoMapDataContext())
{
return db.blogentries.Count();
}
} «
COMMENT: AUTO CARE

JAN 31, 2013 - 05:35:56 AM
COMMENT: AUTOMATIVE VAHICAL

JAN 31, 2013 - 05:36:09 AM
COMMENT: CAR REPAIRS

JAN 31, 2013 - 05:36:21 AM