Skip to content
This repository has been archived by the owner on Dec 13, 2021. It is now read-only.

Commit

Permalink
Merge pull request #166 from leekelleher/develop
Browse files Browse the repository at this point in the history
Release 0.9.0-beta
  • Loading branch information
leekelleher committed Apr 27, 2016
2 parents a6cefa5 + d9432b6 commit 8cf0fc0
Show file tree
Hide file tree
Showing 121 changed files with 3,757 additions and 2,838 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
<img height="100" src="docs/assets/img/ditto.png" style="margin-bottom: 20px">
<img height="100" src="docs/assets/img/ditto.png" style="margin-bottom: 20px" alt="Ditto logo" title="Ditto">

[![Build status](https://img.shields.io/appveyor/ci/leekelleher/umbraco-ditto.svg)](https://ci.appveyor.com/project/leekelleher/umbraco-ditto)
[![Documentation Status](https://readthedocs.org/projects/umbraco-ditto/badge/?version=latest)](https://readthedocs.org/projects/umbraco-ditto/?badge=latest)
[![NuGet release](https://img.shields.io/nuget/v/Our.Umbraco.Ditto.svg)](https://www.nuget.org/packages/Our.Umbraco.Ditto)
[![Our Umbraco project page](https://img.shields.io/badge/our-umbraco-orange.svg)](https://our.umbraco.org/projects/developer-tools/ditto)
[![Chat on Gitter](https://img.shields.io/badge/gitter-join_chat-green.svg)](https://gitter.im/leekelleher/umbraco-ditto)

Ditto is a lightweight model mapper for Umbraco. It offers a generic solution to the problem of using **strongly-typed models in your MVC views**.
Ditto is a lightweight view-model mapper for Umbraco. It offers a simple solution to the problem of using **strongly-typed models in your MVC views**.
There are no 3<sup>rd</sup> party dependencies, other than Umbraco core itself.

#### Is Ditto a "Yet Another Code-First" approach?
**Is Ditto a "Yet Another Code-First" approach?**

Nope! The goal of Ditto is to provide a simple way to convert your content/media nodes (e.g. `IPublishedContent`) to your desired view-model object.
_Nope!_ The goal of Ditto is to provide a simple way to convert your content/media/member nodes (e.g. `IPublishedContent`) to your desired view-model object.

There is absolutely zero intention of generating Document-Types from your view-models.


## Documentation and notes

> Ditto has been developed against **Umbraco v6.2.5** and will support that version and above.
Expand Down Expand Up @@ -52,6 +53,7 @@ Have a question?
* Thanks to [Darren Ferguson](https://github.com/darrenferguson) for inspiration in his article "[Mapping Umbraco content to POCOs for strongly typed views](http://24days.in/umbraco/2013/mapping-content-to-pocos/)" on the [24 days in Umbraco](http://24days.in/umbraco/) advent calender.
* Thanks to [Jeavon Leopold](https://github.com/Jeavon) for being a rockstar and adding AppVeyor support.
* Thanks to [Hendy Racher](https://github.com/Hendy) for testing and contributions.
* Thanks to [Jamie Pollock](https://github.com/jamiepollock) for continued support, feedback and encouragement.


## License
Expand Down
23 changes: 18 additions & 5 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# version format
version: 0.8.4.{build}
version: 0.9.0.{build}

# UMBRACO_PACKAGE_PRERELEASE_SUFFIX if a rtm release build this should be blank, otherwise if empty will default to alpha
# example UMBRACO_PACKAGE_PRERELEASE_SUFFIX=beta
init:
- set UMBRACO_PACKAGE_PRERELEASE_SUFFIX=
- set UMBRACO_PACKAGE_PRERELEASE_SUFFIX=beta

cache:
- src\packages -> **\packages.config # preserve "packages" directory in the root of build folder but will reset it if packages.config is modified

build_script:
- build-appveyor.cmd
Expand All @@ -18,7 +21,7 @@ artifacts:
- path: artifacts\*.zip

deploy:
# MyGet Deployment for builds & releases
# MyGet (Ditto feed) Deployment for builds & releases
- provider: NuGet
server: https://www.myget.org/F/umbraco-ditto/
symbol_server: https://nuget.symbolsource.org/MyGet/umbraco-ditto
Expand All @@ -28,7 +31,17 @@ deploy:
on:
branch: develop

# GitHub Deployment for releases
# MyGet (Umbraco Community feed) Deployment for builds & releases
- provider: NuGet
server: https://www.myget.org/F/umbraco-packages/
symbol_server: https://nuget.symbolsource.org/MyGet/umbraco-packages
api_key:
secure: Q1/4K8VSwr7BjwmKDTef8y5lOc7S+jK9ELuWy67y6OVRpjxmnF9M3Gfs1kT+ir8x
artifact: /.*\.nupkg/
on:
branch: develop

# GitHub Deployment for releases
- provider: GitHub
auth_token:
secure: pEozEGTqJutQwOidJU6BTB+Ix0NV4vrUnomhfeqheVz4RNwfxjEYLoqR4XabhlPz
Expand All @@ -39,7 +52,7 @@ deploy:
branch: master
appveyor_repo_tag: true # deploy on tag push only

# NuGet Deployment for releases
# NuGet Deployment for releases
- provider: NuGet
server:
api_key:
Expand Down
12 changes: 7 additions & 5 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## What is Ditto?

Ditto is a model mapper specifically designed to map `IPublishedContent` objects to a custom type. The goal is to easily enable the use of strongly-typed models within your MVC views.
Ditto is a view-model mapper specifically designed to map `IPublishedContent` objects to a custom type. The goal is to easily enable the use of strongly-typed models within your MVC views.

Ditto will automatically map the properties from `IPublishedContent` with the properties of the your model object (POCO class) based on naming conventions.

Expand All @@ -14,17 +14,19 @@ The real question is "why have strongly-typed models?", this leads to cleaner MV

## How do I use Ditto?

First, you need a destination type to work with, once populated, this will be your view-model. The design of the view-model can be influenced by the associated Document Type from Umbraco, but it doesn't necessarily have to be. Ditto will attempt to match up the property and member names of the `IPublishedContent` object. For example if you have a property alias on your Document Type called `"bodyText"`, then this will automatically be mapped to the destination object's property with the name `BodyText`.
First, you need a destination type to work with, once constructed, this will be your view-model. The design of the view-model can be influenced by the associated Document Type from Umbraco, but it doesn't necessarily have to be. Ditto will attempt to match up the property and member names of the `IPublishedContent` object. For example if you have a property alias on your Document Type called `"bodyText"`, then this will automatically be mapped to the destination object's property with the name `BodyText`.

Once you have your type, and a reference to Ditto, you can perform a mapping, using the `.As<T>()` extension method.
> Note: The property-aliases are case-insensitive, so you could name your object's property `BoDyTeXt` if you really _really_ wanted to. Ditto would still map it.
Once you have your type and a reference to Ditto, you can perform a mapping, using the `.As<T>()` extension method.

```csharp
var viewModel = Model.Content.As<MyViewModel>();
```

For more detailed examples, please see the [Basic usage](usage) section, followed by [Advanced usage](usage).
For more detailed examples, please see the [Basic usage](usage-basic) section, followed by [Advanced usage](usage-advanced-attributes).


## Where do I configure Ditto?

Ditto does not require any pre-configuration within your website/web-application. For complex mappings, you can decorate your model type with custom attributes, typically these would be [`ValueResolvers`](usage-advanced-valueresolvers) or [`TypeConverters`](usage-advanced-typeconverters), (or a combination of both).
Ditto does not require any pre-configuration within your website/web-application. For complex mappings, you can decorate your model type with custom attributes, typically these would be [`Processors`](usage-advanced-processors).
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Ditto

Ditto is a lightweight model mapper for Umbraco. It offers a generic solution to the problem of using **strongly-typed models in your MVC views**.
Ditto is a lightweight view-model mapper for Umbraco. It offers a simple solution to the problem of using **strongly-typed models in your MVC views**.


## Where can I get it?
Expand Down
5 changes: 3 additions & 2 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ To [install from NuGet](https://www.nuget.org/packages/Our.Umbraco.Ditto), you c
PM> Install-Package Our.Umbraco.Ditto
```

We also have a [MyGet package repository](https://www.myget.org/gallery/umbraco-ditto) - for bleeding-edge / development releases.
We also have a [MyGet package repository](https://www.myget.org/gallery/umbraco-packages) - for bleeding-edge / development releases.

## Manual build

If you prefer, you can compile Ditto yourself, you'll need:

* Visual Studio 2012 (or above)
* [Visual Studio 2012 (or above, including Community Editions)](https://www.visualstudio.com/downloads/)
* Microsoft Build Tools 2013 (aka [MSBuild 12](https://www.microsoft.com/en-us/download/details.aspx?id=40760))

To clone it locally run the following git commands:

Expand Down
58 changes: 58 additions & 0 deletions docs/upgrade-090.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
## Upgrading to v0.9.0

With Ditto v0.9.0 the introduction of Processors has made an overall breaking change for developers who have built custom TypeConverters or ValueResolvers with previous Ditto versions. The intention of Processors are to combine the power and flexibility of both TypeConverters and ValueResolvers together.

### TypeConverters

Here are some notes on how to refactor your custom TypeConverters to use the new Processors.

#### Functional changes

* Change the class inheritance from `DittoConverter` to `DittoProcessor`
* _If applicable_, remove the `CanConvertFrom` method, (this is no longer relevant to the processor workflow)
* Change the main `ConvertFrom` name and method signature from:

```csharp
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
```
to

```csharp
public override object ProcessValue()
```

* Change any variable references (inside the `ConvertFrom` method) to the new inherited properties:
* (`ITypeDescriptorContext`) `context` is now `Context` (capitalized)
* (`CultureInfo`) `culture` is now accessible via the `Context` object, e.g. `Context.Culture`
* (`object`) `value` is now `Value` (capitalized)

The rest of your old TypeConverter logic should remain the same.

> If you do encounter any major issues in refactoring a TypeConverter, please do let us know. We would like these notes to cover as much as they can.

#### Cosmetic changes

* If your custom TypeConverter class name has a "Converter" suffix, consider changing this to use the "Processor" suffix. This makes no change in how Ditto uses the class, it is purely for cosmetic and conventional reasons.


### ValueResolvers

Here are some notes on how to refactor your custom ValueResolvers to use the new Processors.

* Change the class inheritance from `DittoValueResolver` to `DittoProcessor`
* Change the main `ResolveValue` name and method signature from:

```csharp
public override object ResolveValue()
```

to

```csharp
public override object ProcessValue()
```

The rest of your old ValueResolver logic should remain the same.

> If you do encounter any major issues in refactoring a ValueResolver, please do let us know. We would like these notes to cover as much as they can.
68 changes: 42 additions & 26 deletions docs/usage-advanced-attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
To extend the mapping functionality, Ditto offers several attributes to decorate your POCO models:

* [`UmbracoProperty`](#umbracoproperty)
* [`AltUmbracoProperty`](#altumbracoproperty)
* [`UmbracoProperties`](#umbracoproperties)
* [`UmbracoDictionary`](#umbracodictionary)
* [`AppSetting`](#appsetting)
* [`DittoIgnore`](#dittoignore)
* [`UmbracoPicker`](#umbracopicker)
* [`CurrentContentAs`](#currentcontentas)
* [`DittoIgnore`](#dittoignore)
* [`AppSetting`](#appsetting)


---

Expand All @@ -26,6 +30,15 @@ public string Content { get; set; }
Now Ditto will know to map the POCO's `Content` property to the DocumentType's "bodyText" property.


## `AltUmbracoProperty`

> // TODO: Add example
>
## `UmbracoProperties`

> // TODO: Add example

## `UmbracoDictionary`

Expand All @@ -39,31 +52,9 @@ public string ReadMoreLabel { get; set; }
```


## `AppSetting`

This attribute can be used for when you would like to populate your POCO model property with a value from the `Web.config` `<appSettings>` section. By supplying the key name for the app-setting, the value will be populated.

For example, if you wanted to display the Umbraco version number, you could do this:

```csharp
[AppSetting("umbracoConfigurationStatus")]
public string UmbracoVersion { get; set; }
```


## `DittoIgnore`

For situations where you would rather that Ditto did not attempt to map a DocumentType property with one of your POCO model properties, you can use the `DittoIgnore` attribute:

```csharp
[DittoIgnore]
public string Image { get; set; }
```

When you map your content node, the ignored property (in this example, `Image`) will be set as the default value for that type (in this case that would be `null`).

The `DittoIgnore` attribute is useful for when you want to construct more complex POCO models.
## `UmbracoPicker`

> // TODO: Add example

## `CurrentContentAs`
Expand Down Expand Up @@ -101,3 +92,28 @@ var poco = Model.Content.As<MyModel>();
<title>@poco.MetaData.MetaTitle</title>
```


## `DittoIgnore`

For situations where you would rather that Ditto did not attempt to map a DocumentType property with one of your POCO model properties, you can use the `DittoIgnore` attribute:

```csharp
[DittoIgnore]
public string Image { get; set; }
```

When you map your content node, the ignored property (in this example, `Image`) will be set as the default value for that type (in this case that would be `null`).

The `DittoIgnore` attribute is useful for when you want to construct more complex POCO models.


## `AppSetting`

This attribute can be used for when you would like to populate your POCO model property with a value from the `Web.config` `<appSettings>` section. By supplying the key name for the app-setting, the value will be populated.

For example, if you wanted to display the Umbraco version number, you could do this:

```csharp
[AppSetting("umbracoConfigurationStatus")]
public string UmbracoVersion { get; set; }
```
30 changes: 30 additions & 0 deletions docs/usage-advanced-processors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Processors

The key feature of Ditto is the ability to process a value (typically from an `IPublishedContent` property) and set it to the property of the target view-model. To do this we use a Processor (or a combination of Processors).

While Ditto covers the most common types of processing, (via the use of [attributes](usage-advanced-attributes), there may be scenarios where you may need a little help in processing custom (or complex) values.

Traditionally any custom processor logic would be typically done within an MVC controller. However, if the logic is only relevant to the mapping operation, then it may clutter your controller code and be better suited as a custom `Processor`.

For example, let's look at having a calculated value during mapping, say that you wanted to display the number of days since a piece of content was last updated:

```csharp
public class MyModel
{
[MyCustomProcessor]
public int DaysSinceUpdated { get; set; }
}

public class MyCustomProcessor : DittoProcessorAttribute
{
public override object ProcessValue()
{
var content = Value as IPublishedContent;
if (content == null) return null;

return (DateTime.UtcNow - content.UpdateDate).Days;
}
}
```

Once mapped, the value of `DaysSinceUpdated` would contain the number of days difference between the content item's last update date and today's date (UTC now).
38 changes: 3 additions & 35 deletions docs/usage-advanced-typeconverters.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,7 @@
## Type Converters

Sooner or later you'll reach a point where you will want to map a DocumentType property with a complex .NET type (either from within the .NET Framework, or custom). To map these types with Ditto, you can use a standard .NET `TypeConverter`.
As of Ditto v0.9.0 TypeConverters have been deprecated and replaced with [Processors][usage-advanced-processors].

> If you are not familiar with .NET TypeConverters, please read Scott Hanselman's blog post: [TypeConverters: There's not enough TypeDescripter.GetConverter in the world](http://www.hanselman.com/blog/TypeConvertersTheresNotEnoughTypeDescripterGetConverterInTheWorld.aspx). This gives a good 'real-world' understanding of their purpose.
>
> Then from there, refer to the MSDN documentation on [How to: Implement a Type Converter](http://msdn.microsoft.com/en-gb/library/ayybcxe5.aspx)
If you have developed a custom TypeConverters against a previous version of Ditto, then [please refer to this migration guide](upgrade-090).

Now with our example, let's say that you wanted the `BodyText` property to be of type `HtmlString` (rather than a basic `string`). You can reference a custom `TypeConverter` by adding the following attribute to the POCO property:

```csharp
[TypeConverter(typeof(MyCustomConverter))]
public HtmlString BodyText { get; set; }
```

Then when the POCO property is populated the (raw) value (from `IPublishedContent`) will be processed through the custom `TypeConverter` and converted to the desired .NET type.

Here is the example code for the `MyCustomConverter`, that converts a `string` to a `HtmlString` object:

```csharp
public class MyCustomConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;

return base.CanConvertFrom(context, sourceType);
}

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string)
return new System.Web.HtmlString((string)value);

return base.ConvertFrom(context, culture, value);
}
}
```
> **Note:** It is important to note that when getting a property-value from Umbraco, any associated TypeConverters (for the target value-type) will still be called. In a nutshell, this means that you can use TypeConverters with Umbraco, but not Ditto.
Loading

0 comments on commit 8cf0fc0

Please sign in to comment.