Writing a Custom Hive Provider using objects as datasource - umbraco5

Im trying to create a hive provider that would be able to work towards some objects.
An object may look something like this
public class MyContent
{
public System.Collections.Generic.List Content { get; set; }
}
public class ContentExample
{
public string Title { get; set; }
public string Text { get; set; }
}
public class MyFiles
{
public System.Collections.Generic.List Files { get; set; }
}
public class FileExample
{
public System.IO.FileInfo File { get; set; }
}
I've downloaded and checked the two Hive providers from the Visual Studio Gallery (Umbraco 5 Hive Provider and Umbraco 5 Simple Hive Provider), but the lack of documentation is a bit disturbing. I also downloaded some of the other example hives, like the Wordpress hive provider, but that one is rather different from the ones in the Visual Studio Gallery.
The Idea
Im used to working with stuff like ObjectDataSource, the example above could be complemented with full CRUD if required.
Now, I assume one Hive provider would be able to serve different parts of Umbraco with content (right?). Just set up a new Repository and go? I have now clue how to connect all parts or even how to get the data into the provider yet.
Any help in how I could bring all pieces together?
Thanks

The first step is to take a step back and evaluate your business requirements. Will you allow for users to be updating the information with forms in the frontend? Do you need a tree editor for the content in the backoffice? Do you need to be work with data outside of the built-in ORM?
If the answer to these is no, a hive provider is overkill. Evaluate solutions using either a simple surface controllers, or just a custom document type. Umbraco 5 is a full EAV/CR system, so unlike some CMS products, you'll be able to represent any rdbs structure you can imagine
ContentExample could be represented be a document type called 'Article', which has properties Title and Text. Just by defining this document type we're instantly given add and edit forms for our back office users in our content section. We can even restrict which nodes are able to have children of type 'Article', e.g News.
In the same way, an upload control is a field type that allows you to attach files to your document.
So what's point of a custom hive provider?
The goal of a custom hive provider is to unify CRUD actions for data access layers.
As a result data can be stored in the baked-in nhibernate orm, custom tables, rss feeds, or even flat files, while still using a common interface to retrieve and update it. If this sounds like what you're aiming for, read on.
Going back to the business requirements, specifically, where do you want to actually store the data?--Given that you have some fields and properties related to flat file storage, let's say that one TypedEntity (a model) is equivelant to one file and write some pseduocode:
The first step, is as you say 'get the data into the repository.' This involves going back to that VS template and filling in the 'not implemented' methods with your logic for storing and retrieving data.
protected override void PerformAddOrUpdate(TypedEntity entity)
{
// step 1: serialize the typed entity to xml
// step 2: write the file to the hdd, making sure that the file name is named using the hive id so that we can pull it back later.
}
Once you've written the data access layer, or DAL, you can hook it up in the hive config, giving it url to match. e.g. rather than matching content:\\, yours might match on file-manager:\\
We can allow our backoffice users to be able to add new entities (indirectly, new files) by writing a custom tree, and we can display the results to our front-end users via macros.

Related

Proper design technique

I am creating an asp.net mvc4 application that will ask the user a set of questions based on a particular criteria that they enter. Each question is stored in a table and only those questions that meet the criteria will be displayed to the end user.
I am using a viewmodel that combines information from a couple of different tables. Basically it has a list of Questions and an inspection id to tie all the test together. My question is what is the proper oo design technique for populating the viewmodel.
Should the method / methods for populating the viewmodel reside within the viewmodel class itself? Basically passing the entities into the viewmodel and allow it to populate itself.
Should there be a new class that you send in the entities in and it returns the viewmodel?
Or is there a better way to do this.
yes, your approach is valid.
Consider the following example in your model:
public List<Questions> Questions
{
get {
QuestionRepository Rep = new QuestionRepository();
return Rep.ObtainQuestions(ClientAge,ClientType)
}
}
public int ClientAge { get; set; }
public ClientTypeEnum ClientType { get; set; }
the getter in the Questions property includes all the logic. as long as the clientAge and the ClientType properties have valid values, the question list will be populated. this avoids having to set the data in every action method where you need to populate the property.
in the example I am getting the data from a repository but you could get it from an ORM like entity framework, or any other source.
you can google the term skinny controllers and read up more on the recomendations and best practices.

MVC SPA w/o EF: You must write an attribute 'type'='object' after writing the attribute with local name '__type'

So I have a very normalized model, and I'm trying to create a single page application in MVC4 which wants to use an entity framework object. My problem is I can't manage to create an entity in EF with the kind of complex mapping that I need (I have checked multiple guides, but I can't seem to make one entity from multiple tables that contain different primary keys... I found a solution using updateable views, but that's really just pushing the abstraction down to the db layer).
So I thought I could create a POCO object using an EF query to create the object, then on insert/update/delete I could just take the POCO data and update the underlying 3 tables.
Well I hit a roadblock just trying to tweak an existing working controller to try and learn what's going on.
Let's imagine I have a working SPA controller that looks like this:
public partial class FooController : DbDataController<aspnetEntities>
{
public IQueryable<Foos> GetFoos() { ... }
}
I just change it a bit to return my new POCO data object Bar, which let's imagine has the exact same fields as Foo for the moment:
public partial class FooController : DbDataController<aspnetEntities>
{
public IQueryable<Bars> GetBars() { ... }
}
Over in FooViewModel.js I update the operation name to GetBars, and the type from
var entityType = "Foo:#Models";
to
var entityType = "Bar:#Models";
I hit my operation directly and I get:
OLD
<ArrayOfFoo><Foo><Property>true</Property></Foo></ArrayOfFoo>
NEW
<ArrayOfBar><Bar><Property>true</Property></Bar></ArrayOfBar>
So the controller looks like it's giving me what I expect, but when I try to put the whole thing together the SPA flashes up:
You must write an attribute 'type'='object' after writing the attribute with local name '__type'.
I'm guessing somehow I need to get type data into KO? I'm not sure where that might be however, I've been crawling through the JS for hours, but I'm not even clear on where it's failing. Any input would be greatly appreciated.
The problem you are experiencing is connected to the fact you are using POCO instead of the standard EF. It should be related to the webapi serializer that somehow doesn't recognize the class as serializable. Anyway it is a bug that will be removed in the RC. Give a look to this thread for workarounds:
http://forums.asp.net/t/1773173.aspx/1?You+must+write+an+attribute+type+object+after+writing+the+attribute+with+local+name+__type+

Patterns for building social network type applications?

I need to design / architect / develop a web based social network type application.
Basic functionality:
- users create accounts on the system
- users agree to "friend" each other
- users create content within system
- users specifies which friends may view/edit content that they created
Surely this core functionality has been created many times before? Are there any best practice patterns out there for how to implement this sort of thing?
I'm most interested in how the database for this would look.
What would this look like from a SQL perspective (any database)?
What would this look like from a NOSQL perspective (any NOSQL database)?
The thing I am most interested in, is how is the question of "content visibility" solved within the database? i.e. how does the database/application ensure that only approved friends may see the user created content?
Thanks
First thing to get out the way is the database, an SQL one would just look like a normalised sql database. What else could it look like? A nosql database would look like a bunch of name value pair files.
Three approaches to building a social web site after and only after you do a shed load of research on existing popular and unpopular ones to ascertain their architecture and the markets that that they are aimed at, and the particular services that they offer to these markets.
Roll your own from scratch (and or use a framework). Like Facebook, Beebo, Myspace et al. This is obviously the longest route to getting there but it does mean you have something to sell when you do. Both the platform and the membership and the USP are yours to sell to Rupert Murdoch or whomever.
Use a CMS that lends itself to social site and use the basic functionality, plus the plug-ins plus your own inspiration to hit your target market. In this area Drupal is often used (i have used it successfully as well) but Joomla, Xaraya and many other both free and paid for can be used. Yep more research. Less to sell here when Rupert gives you a bell as the base tool is probably GPL'd
Use one of the provided system where you sign up and then use the tools to build your own but all the goodies are provided, These are known as white label sites. Start looking here. Here you have little to sell on if someone wants to take you over.
How is "content visibility" handled. Initially of course the site builder makes a decision on who can see content. Owners only, friends, registered users, the general public? etc. But this decision must fir in with the aims and policies of the site. The best way then to handle this is through Role Based Access RBAC see here for details
When you say you "need to design / architect / develop" is this because of an overwhelming inner urge or because someone is paying you?
Either way remember the social web space is very very crowded. If you are just building another YouTube, or FaceBook then you are unlikely to be able to generate the critical mass of number required to make such a site commercially successful.
If it is for a niche market not already catered for, e.g. "The Peckham and Brockley Exotic Bird Fanciers Club" then you know what you market is and what features will be required so any of the above options you deem the easiest and cheapest can be used but that is up to you to analyse and execute.
You may of course have an idea for a social site that is mainstream and is not covered by the other, i.e. you have spotted the mythological "gap in the market". In this case go for it but prepare to be disappointed. Or not.
Your design should be maintenable. This is what I have in my project.
1.) Application.Infrastructure
Base classes for all businessobjects, busines object collection, data-access classes and my custom attributes and utilities as extension methods, Generic validation framework. This determines overall behavior organization of my final .net application.
2.) Application.DataModel
Typed Dataset for the Database.
TableAdapters extended to incorporate Transactions and other features I may need.
3.) Application.DataAccess
Data access classes.
Actual place where Database actions are queried using underlying Typed Dataset.
4.) Application.DomainObjects
Business objects and Business object collections.
Enums.
5.) Application.BusinessLayer
Provides manager classes accessible from Presentation layer.
HttpHandlers.
My own Page base class.
More things go here..
6.) Application.WebClient or Application.WindowsClient
My presentation layer
Takes references from Application.BusinessLayer and Application.BusinessObjects.
Application.BusinessObjects are used across the application and they travel across all layers whenever neeeded [except Application.DataModel and Application.Infrastructure]
All my queries are defined only Application.DataModel.
Application.DataAccess returns or takes Business objects as part of any data-access operation. Business objects are created with the help of reflection attributes. Each business object is marked with an attribute mapping to target table in database and properties within the business object are marked with attributes mapping to target coloumn in respective data-base table.
My validation framework lets me validate each field with the help of designated ValidationAttribute.
My framrwork heavily uses Attributes to automate most of the tedious tasks like mapping and validation. I can also new feature as new aspect in the framework.
A sample business object would look like this in my application.
User.cs
[TableMapping("Users")]
public class User : EntityBase
{
#region Constructor(s)
public AppUser()
{
BookCollection = new BookCollection();
}
#endregion
#region Properties
#region Default Properties - Direct Field Mapping using DataFieldMappingAttribute
private System.Int32 _UserId;
private System.String _FirstName;
private System.String _LastName;
private System.String _UserName;
private System.Boolean _IsActive;
[DataFieldMapping("UserID")]
[DataObjectFieldAttribute(true, true, false)]
[NotNullOrEmpty(Message = "UserID From Users Table Is Required.")]
public override int Id
{
get
{
return _UserId;
}
set
{
_UserId = value;
}
}
[DataFieldMapping("UserName")]
[Searchable]
[NotNullOrEmpty(Message = "Username Is Required.")]
public string UserName
{
get
{
return _UserName;
}
set
{
_UserName = value;
}
}
[DataFieldMapping("FirstName")]
[Searchable]
public string FirstName
{
get
{
return _FirstName;
}
set
{
_FirstName = value;
}
}
[DataFieldMapping("LastName")]
[Searchable]
public string LastName
{
get
{
return _LastName;
}
set
{
_LastName = value;
}
}
[DataFieldMapping("IsActive")]
public bool IsActive
{
get
{
return _IsActive;
}
set
{
_IsActive = value;
}
}
#region One-To-Many Mappings
public BookCollection Books { get; set; }
#endregion
#region Derived Properties
public string FullName { get { return this.FirstName + " " + this.LastName; } }
#endregion
#endregion
public override bool Validate()
{
bool baseValid = base.Validate();
bool localValid = Books.Validate();
return baseValid && localValid;
}
}
BookCollection.cs
/// <summary>
/// The BookCollection class is designed to work with lists of instances of Book.
/// </summary>
public class BookCollection : EntityCollectionBase<Book>
{
/// <summary>
/// Initializes a new instance of the BookCollection class.
/// </summary>
public BookCollection()
{
}
/// <summary>
/// Initializes a new instance of the BookCollection class.
/// </summary>
public BookCollection (IList<Book> initialList)
: base(initialList)
{
}
}
a Graph Database like http://www.neo4j.org is a choice to look at. It lends itself very well to both the social network (e.g. http://blog.neo4j.org/2009/09/social-networks-in-database-using-graph.html) and the ACL-based security (e.g. http://wiki.neo4j.org/content/ACL ).
You should first study the existing social networks out there (Facebook, Myspace, etc). There is a fair amount of information available about how they are implemented.
The key to success for social networks is not the technology on which it is based but the problems they solve for the users. If the users like it, you're doomed for success even if your technology is crap.
[EDIT] How is it implemented? Check any SQL-based user role system. In this case, every user is also a role which can be added as "allowed to access" to any object. Depending on how many objects you have and how fine grained the control should be, that can mean that you have a table with three columns: OBJECT, USER, ACCESS_TYPE where ACCESS_TYPE can be one of OWNER, READ (friend), WRITE (close friend).
This table will become pretty large but a few 100 million rows is not uncommon for todays databases anymore.
As Aaroon pointed out, you should first ask youself what problem you want to solve.
What content do you want people to share? Should it really be visible only to friends? It is much easier and scalable if you make content publicly visible, because what content is displayed is not dependent on who is watching the page and you can cache it easily. Publicly available user-generated content attracts new users.
If you want to restrict access and give to the user the opportunity to attach groups of friends to a resource I would go with a simple group-based access control. Let each resource have a group of users which can edit the resource and a group of users who can see it.
That way each resource has two single value attributes, and each user belons to a finite number of group. You can attach the view-group and edit-group attributes to a document stored in a NOSQL database, a search engine like Lucene/Sphinx or a row in a SQL database. When querying for content available for the user, pass all groups the user belongs to (in SQL you would use IN clause, in Sphinx setFilter('view-group', array(2,3,4)). The database would return only content available for the user. Because you are attaching only 2 integer values (view-group and edit-group) to a document, you can store them in memory which makes the search fast and scalable.
In the end it looks like Elgg or Dolphin might meet our requirements. These appear to be PHP frameworks for rolling your own social network. I looked at the Facebook platform but nowhere did it clearly explain just what it is - it appears to be the facebook code but perhaps it is only the code for an addon API or something.

Realize entity copy on NHibernate update

How can I make such behaviuor in NHibernate:
There is an entity called User in my domain
// I ommit mapping attributes
public class User
{
int Id {get; set;}
int pId {get; set;}
//....other props, such as Login, Name, email...
}
I need to make full copy of it, when updating. pId must be set to original Id. Old entity must be untouched.
So this must be like some versioning system, where pId - is immutable identity, and Id - is like version. I`ve tried to use Version mapping attribute, but it just updates Version field, withou recreating full entity. What approach will be better?
I wrote a versioning system for our application. I split the versioned object into two classes, one that represents the whole object and one for its versions.
In our software, the versioning is part of the business logic. The application provides access to the history and the user has some control over the versioning.
A new version is therefore created in memory. You need to perform a deep-copy. You could implement this by implementing an interface in the root entity and all its children. This interface provides a method DeepCopy which is recursively called through the object graph.
There is also a protected MemberwiseCopy method in object, which could be helpful. It does not a deep copy.
We didn't want the pain to maintain the code which copies each single property. So we are using serialization to copy an object graph in memory:
public static T CopyDataContract<T>(T obj)
{
NetDataContractSerializer serializer = new NetDataContractSerializer();
using (MemoryStream stream = new MemoryStream())
{
serializer.Serialize(stream, obj);
stream.Position = 0;
return (T)serializer.Deserialize(stream);
}
}
Additionally, we have methods in the entities which reset the ids and do some other cleanup. This is also done recursively though the object graph.
For now, it works fine. In the future we probably need to refactor it to the interface implementation, which is a bit cleaner.
Depending on whether history is NOT part of your domain logic I'd suggest using triggers. By not being part of domain logic I mean - you don't need to show it to users, you don't make copies out of historical version.
By using triggers you have several options - the simplest (and implying that you really need to save history only for handful of tables) - would be having a separate _history table that's a copy of your original table.
All in all it really depends on what exactly you are after.

Persisting Blob Streams with NHibernate

If I have a class declared as:
public class MyPersistentClass
{
public int ID { get; set; }
public Stream MyData {get;set; }
}
How can I use NHibernate's mappings to persist the MyData property to and from the database?
You could use a Stream using a custom type and map it according to your storage needs. But there are some issues with using the Stream object as I mention in my blog series about lazy streaming of BLOBs and CLOBs with NHibernate.
What you really need is a Blob object that in turn can create a Stream to read data from. Since Stream contains information about the position you're reading from and expects to be closed and disposed of it can create some issues when used directly in a domain model.
I would suggest that you take a look at the blog series as well as the source code of the NHibernate.Lob project. It includes various mapping options for just such a problem. A little scarcely documented so far but more is coming.