How can I create my own elements in Orchard Create new page window
Image URL :
https://drive.google.com/file/d/0B0LukXeHz5VdREtvd19GSHZ1Tm8/view?usp=sharing
This has been answered here: http://orchard.codeplex.com/discussions/643710
Copied from CodePlex:
You can create your own elements by implementing classes that derive from the Element class in the Orchard.Layouts.Framework.Elements namespace. You also need to implement an element driver for your element (even if it contains no members, the TypedElementHarvester relies on this to discover elements).
Checkout the Html element for a good example.
Here's an example of a custom element:
using Orchard.Layouts.Framework.Elements;
public class MyElement : Element {
public override LocalizedString DisplayText {
get { return T("My Custom Element"); }
}
public int SomeCustomProperty {
get { return this.Retrieve(x => x.SomeCustomProperty); }
set { this.Store(x => x.SomeCustomProperty, value); }
}
}
And here is its driver:
using Orchard.Layouts.Framework.Drivers;
public class MyElementDriver : ElementDriver<MyElement> {
// Optionally override members like BuildEditor and UpdateEditor similar to creating content part drivers.
}
For complete examples, checkout the source code in the Orchard.Layouts module, specifically the Elements and Drivers folders.
Let me know if you have any further questions.
Related
I am an Orchard CMS beginner and I do not understand how to get and display a list of items in a view.
I've read the article Writing a ContentPart but the examples show how to use 2 properties instead of a list:
Driver
return ContentShape("Parts_Map", () => shapeHelper.Parts_Map(
Longitude: part.Longitude,
Latitude: part.Latitude));
View
<img alt="Location" border="1" src="http://maps.google.com/maps/api/staticmap?
&zoom=14
&size=256x256
&maptype=roadmap
&markers=color:blue|#Model.Latitude,#Model.Longitude
&sensor=false" />
I want to use a list of items in a view.
I've also read the article Orchard CMS Custom Widget View but i do not understand how it works, especially the following line:
var files = (IContentQuery<FilePart>)Model.Files;
Where can i find additional examples?
Is it below correct? I Use IContentManager contentManager for transfer data to view.
Driver:
public class MyModuleWidgetPartDriver : ContentPartDriver
{
private readonly IContentManager contentManager;
public MyModuleWidgetPartDriver(IContentManager contentManager)
{
this.contentManager = contentManager;
}
protected override DriverResult Display(MyModuleWidgetPart part, string displayType, dynamic shapeHelper)
{
var MyModuleItems = this.contentManager.List<MyModulePart>(MyModulePart.ContentTypeName).ToArray();
// List of items
var MyModuleItemsViewModel = MyModuleItems.Select(MyModule => new MyModuleItemsViewModel
{
Title = MyModule.Title,
Html = MyModule.Html
});
return ContentShape("Parts_MyModules", () => shapeHelper.Parts_MyModules(
promo: Json.Encode(MyModuleItemsViewModel)));
}
MyModulePart:
public class MyModulePart : ContentPart
{
public const string ContentTypeName = "MyModule";
public string Title
{
get { return this.As<ITitleAspect>().Title; }
}
public string Html
{
get { return this.As<BodyPart>().Text; }
}
}
View\Parts\MyModule.cshtml:
#{
var MyModuleItems = Model.promo;
}
You can set anything you need in the view onto the shape you're creating from your driver. Do make sure that whenever you perform a "heavy" operation such as querying a database, you do so from within the shape factory lambda (the lambda that actually creates the shape). If you do this outside of the lambda, your query will execute even if your shape won't be displayed, which would obviously be inefficient. For example:
Driver
return ContentShape("Parts_Map", () => {
return shapeHelper.Parts_Map(
MyList: _someService.GetMyListOfData(); // The MyList property will be added on the fly to the Parts_Map shape you're creating, and will be available in the view, whose model is in fact this Parts_Map shape.
Longitude: part.Longitude,
Latitude: part.Latitude);
});
View
<ul>
#foreach(var item in Model.MyList){
<li>#item.SomeProperty</li>
}
</ul>
Remember: Shapes are dynamic objects to which you can add properties on the fly. When "rendering a shape", what really happens is that Orchard locates the appropriate Razor view based on metadata stored with the shape (each shape has a Metadata property), and sets the Model of that view to the shape object.
I created a custom part using the content picker field.
public int UpdateFrom1()
{
ContentDefinitionManager.AlterPartDefinition("BackgroundPart",
builder => builder.WithField("BackgroundImage",
fieldBuilder => fieldBuilder
.OfType("MediaPickerField")
.WithDisplayName("Background Image")));
return 2;
}
public int UpdateFrom2()
{
ContentDefinitionManager.AlterTypeDefinition("Background", cfg => cfg
.WithPart("BackgroundPart")
.Creatable()
.Indexed());
return 3;
}
The service code for getting the data:
public class BackgroundService : IBackgroundService
{
private readonly IRepository<BackgroundPartRecord> _repository;
public BackgroundService(
IRepository<BackgroundPartRecord> repository,
ISignals signals)
{
_repository = repository;
}
public IEnumerable<BackgroundPartRecord> Get()
{
return _repository.Table;
}
}
This works (i can pick content when I create an new item of this type).
Now I want to get a list of all items of my type. I created a service for that and I get a list of my created items. But the items in the list don't have the media picker field. How do I get this content? I want to use this in OnResultExecuting method in a FilterProvider class in my module.
That can't work because you're using the repository API. Repository is a low-level API that is used internally, but should rarely, if ever be used by modules. One of the reasons is that it won't get content items, just part records.
Instead, you need to use one of the querying APIs from ContentManager. That will give you real content items that you can do As on, that will give you access to the content item's fields (those are stored on the Infoset, which is on the content item record), etc.
This or one of the overloads and extension methods should do the trick:
_contentManager.Query<BackgroundPart>()
My current implementation for service and business layer is straight forward as below.
public class MyEntity { }
// Business layer
public interface IBusiness { IList<MyEntity> GetEntities(); }
public class MyBusinessOne : IBusiness
{
public IList<MyEntity> GetEntities()
{
return new List<MyEntity>();
}
}
//factory
public static class Factory
{
public static T Create<T>() where T : class
{
return new MyBusinessOne() as T; // returns instance based on T
}
}
//Service layer
public class MyService
{
public IList<MyEntity> GetEntities()
{
return Factory.Create<IBusiness>().GetEntities();
}
}
We needed some changes in current implementation. Reason being data grew over the time and service & client cannot handle the volume of data. we needed to implement pagination to the current service. We also expect some more features (like return fault when data is more that threshold, apply filters etc), so the design needs to be updated.
Following is my new proposal.
public interface IBusiness
{
IList<MyEntity> GetEntities();
}
public interface IBehavior
{
IEnumerable<T> Apply<T>(IEnumerable<T> data);
}
public abstract class MyBusiness
{
protected List<IBehavior> Behaviors = new List<IBehavior>();
public void AddBehavior(IBehavior behavior)
{
Behaviors.Add(behavior);
}
}
public class PaginationBehavior : IBehavior
{
public int PageSize = 10;
public int PageNumber = 2;
public IEnumerable<T> Apply<T>(IEnumerable<T> data)
{
//apply behavior here
return data
.Skip(PageNumber * PageSize)
.Take(PageSize);
}
}
public class MyEntity { }
public class MyBusinessOne : MyBusiness, IBusiness
{
public IList<MyEntity> GetEntities()
{
IEnumerable<MyEntity> result = new List<MyEntity>();
this.Behaviors.ForEach(rs =>
{
result = rs.Apply<MyEntity>(result);
});
return result.ToList();
}
}
public static class Factory
{
public static T Create<T>(List<IBehavior> behaviors) where T : class
{
// returns instance based on T
var instance = new MyBusinessOne();
behaviors.ForEach(rs => instance.AddBehavior(rs));
return instance as T;
}
}
public class MyService
{
public IList<MyEntity> GetEntities(int currentPage)
{
List<IBehavior> behaviors = new List<IBehavior>() {
new PaginationBehavior() { PageNumber = currentPage, }
};
return Factory.Create<IBusiness>(behaviors).GetEntities();
}
}
Experts please suggest me if my implementation is correct or I am over killing it. If it correct what design pattern it is - Decorator or Visitor.
Also my service returns JSON string. How can I use this behavior collections to serialize only selected properties rather than entire entity. List of properties comes from user as request. (Kind of column picker)
Looks like I don't have enough points to comment on your question. So, I am gonna make some assumption as I am not a C# expert.
Assumption 1: Looks like you are getting the data first and then applying the pagination using behavior object. If so, this is a wrong approach. Lets say there are 500 records and you are showing 50 records per fetch. Instead of simply fetching 50 records from DB, you are fetching 500 records for 10 times and on top of it you are adding a costly filter. DB is better equipped to do this job that C# or Java.
I would not consider pagination as a behavior with respect to the service. Its the behavior of the presentation layer. Your service should only worry about 'Data Granularity'. Looks like one of your customer wants all the data in one go and others might want a subset of that data.
Option 1: In DAO layer, have two methods: one for pagination and other for regular fetch. Based on the incoming params decide which method to call.
Option 2: Create two methods at service level. One for a small subset of data and the other for the whole set of data. Since you said JSON, this should be Restful service. Then based on the incoming URL, properly call the correct method. If you use Jersey, this should be easy.
In a service, new behaviors can be added by simply exposing new methods or adding new params to existing methods/functionalities (just make sure those changes are backward compatible). We really don't need Decorator or Visitor pattern. The only concern is no existing user should be affected.
This question may appear to have been answered before but I have been unable to find exactly what I need. Here is my situation:
// Base class
interface IAnimal {};
public abstract class Animal : IAnimal{}
// Derived classes
interface IDog {}
public class Dog : Animal, IDog { }
interface ICat { }
public class Cat : Animal, ICat { }
interface ITiger { }
public class Tiger : Animal, ITiger { }
interface ILion { }
public class Lion : Animal, ILion { }
// Collection Classes
interface IPets { }
public class Pets
{
IDog dog = new Dog();
ICat cat = new Cat();
}
interface ICircus { }
public class Circus
{
ITiger tiger = new Tiger();
ILion lion = new Lion();
}
I would like to create the collections at run time in an generic Event class by reading in a list animals from xml that would make up the collection. What would be the correct way to accomplish this?
Thanks in advance.
This is kind of an answer to my own question. Maybe this will help others.
I chose a very generic example to illustrate my situation because I have uses for this in many places in Windows Forms, XNA and Silverlight that are all very different.
When I used the Activator, I found out that it assumes the executing assembly. My method is in a library so I had to load a different assembly. Next I had to make sure that I had the right namespace. My base class is in a library and the derived classes are in another namespace so this will require refactoring to properly create the list.
Another problem I found was that the Activator assumes a constructor with no parameters. In my test case all my derived classes are XNA game components with a parameter of type Game.
Have to do some refactoring to test out the interfaces and how the game objects are to interact.
Will be back to this list when I have something further.
Does this sort of example help? (It's from some of my code I happened to have handy.) The key point here is the use of reflection in Activator.CreateInstance(...).
public static List<dynamic> LoadChildEntities(XElement entityElt)
{
var children = new List<dynamic>();
foreach(XElement childElt in entityElt.Elements("entity"))
{
// Look up the C# type of the child entity.
string childTypename = "MyNamespace." + Convert.ToString(childElt.Attribute("type").Value);
Type childType = Type.GetType(childTypename);
if(childType != null)
{
// Construct the child entity and add it to the list.
children.Add(Activator.CreateInstance(childType, childElt));
}
else
{
throw new InvalidOperationException("No such class: " + childTypename);
}
}
return children;
}
If you want a list of IAnimal instead, it wouldn't be too tricky to change.
I'm struggling with implementing a factory object. Here's the context :
I've in a project a custom store. In order to read/write records, I've written this code in a POCO model/separated repository:
public class Id { /* skip for clarity*/} // My custom ID representation
public interface IId
{
Id Id { get; set; }
}
public interface IGenericRepository<T> where T : IId
{
T Get(Id objectID);
void Save(T #object);
}
public interface IContext
{
TRepository GetRepository<T, TRepository>()
where TRepository : IGenericRepository<T>
where T:IId;
IGenericRepository<T> GetRepository<T>()
where T:IId;
}
My IContext interface defines two kind of repositories.
The former is for standard objects with only get/save methods, the later allows me to define specifics methods for specific kind of objects. For example :
public interface IWebServiceLogRepository : IGenericRepository<WebServiceLog>
{
ICollection<WebServiceLog> GetOpenLogs(Id objectID);
}
And it the consuming code I can do one of this :
MyContext.GetRepository<Customer>().Get(myID); --> standard get
MyContext.GetRepository<WebServiceLog, IWebServiceLogRepository>().GetOpenLogs(myID); --> specific operation
Because most of objects repository are limited to get and save operations, I've written a generic repository :
public class BaseRepository<T> : IGenericRepository<T>
where T : IId, new()
{
public virtual T Get(Id objectID){ /* provider specific */ }
public void Save(T #object) { /* provider specific */ }
}
and, for custom ones, I simply inherits the base repository :
internal class WebServiceLogRepository: BaseRepository<WebServiceLog>, IWebServiceLogRepository
{
public ICollection<WebServiceLog> GetByOpenLogsByRecordID(Id objectID)
{
/* provider specific */
}
}
Everything above is ok (at least I think it's ok). I'm now struggling to implement the MyContext class. I'm using MEF in my project for other purposes. But because MEF doesn't support (yet) generic exports, I did not find a way to reach my goal.
My context class is looking like by now :
[Export(typeof(IContext))]
public class UpdateContext : IContext
{
private System.Collections.Generic.Dictionary<Type, object> m_Implementations;
public UpdateContext()
{
m_Implementations = new System.Collections.Generic.Dictionary<Type, object>();
}
public TRepository GetRepository<T, TRepository>()
where T : IId
where TRepository : IGenericRepository<T>
{
var tType = typeof(T);
if (!m_Implementations.ContainsKey(tType))
{
/* this code is neither working nor elegant for me */
var resultType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(
(a) => a.GetTypes()
).Where((t)=>t.GetInterfaces().Contains(typeof(TRepository))).Single();
var result = (TRepository)resultType.InvokeMember("new", System.Reflection.BindingFlags.CreateInstance, null, null, new object[] { this });
m_Implementations.Add(tType, result);
}
return (TRepository)m_Implementations[tType];
}
public IGenericRepository<T> GetRepository<T>() where T : IId
{
return GetRepository<T, IGenericRepository<T>>();
}
}
I'd appreciate a bit of help to unpuzzle my mind with this quite common scenario
Not sure if I've understood you correctly, but I think you're perhaps over complicating things. To begin with, make sure you've designed your code independent of any factory or Dependency Injection framework or composition framework.
For starters lets look at what you want your calling code to look like, this is what you said:
MyContext.GetRepository<Customer>().Get(myID); --> standard get
MyContext.GetRepository<WebServiceLog, IWebServiceLogRepository>().GetOpenLogs(myID);
You don't have to agree with my naming choices below, but it indicates what I undertand from your code, you can tell me if I'm wrong. Now, I feel like the calling would be simpler like this:
RepositoryFactory.New<IRepository<Customer>>().Get(myId);
RepositoryFactory.New<IWebServiceLogRepository>().GetOpenLogs(myId);
Line 1:
Because the type here is IRepository it's clear what the return type is, and what the T type is for the base IRepository.
Line 2:
The return type here from the factory is IWebServiceLogRepository. Here you don'y need to specify the entity type, your interface logically already implements IRepository. There's no need to specify this again.
So your interface for these would look like this:
public interface IRepository<T>
{
T Get(object Id);
T Save(T object);
}
public interface IWebServiceLogRepository: IRepository<WebServiceLog>
{
List<WebServiceLog> GetOpenLogs(object Id);
}
Now I think the implementations and factory code for this would be simpler as the factory only has to know about a single type. On line 1 the type is IRepository, and in line 2, IWebServiceLogRepository.
Try that, and try rewriting your code to simply find classes that implement those types and instantiating them.
Lastly, in terms of MEF, you could carry on using that, but Castle Windsor would really make things much simpler for you, as it lets you concentrate on your architecture and code design, and its very very simple to use. You only ever reference Castle in your app startup code. The rest of your code is simply designed using the Dependency Injection pattern, which is framework agnostic.
If some of this isn't clear, let me know if you'd like me to update this answer with the implementation code of your repositories too.
UPDATE
and here's the code which resolves the implementations. You were making it a bit harder for yourself by not using the Activator class.
If you use Activator and use only one Generic parameter as I've done in the method below, you should be ok. Note the code's a bit rough but you get the idea:
public static T GetThing<T>()
{
List<Type> assemblyTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes()).ToList();
Type interfaceType = typeof(T);
if(interfaceType.IsGenericType)
{
var gens = interfaceType.GetGenericArguments();
List<Type> narrowed = assemblyTypes.Where(p => p.IsGenericType && !p.IsInterface).ToList();
var implementations = new List<Type>();
narrowed.ForEach(t=>
{
try
{
var imp = t.MakeGenericType(gens);
if(interfaceType.IsAssignableFrom(imp))
{
implementations.Add(imp);
}
}catch
{
}
});
return (T)Activator.CreateInstance(implementations.First());
}
else
{
List<Type> implementations = assemblyTypes.Where(p => interfaceType.IsAssignableFrom(p) && !p.IsInterface).ToList();
return (T)Activator.CreateInstance(implementations.First());
}
}