I recently set up this blog and I figured as my first “real” post I could go through the steps it took to set this up. I gleaned quite a bit of information from quite a few sites, but I still felt there could be some improvements on this topic. I’ve made sure to include all of my references in the bottom of the post.

Creating the site

This assumes you have a version of ruby loaded. More information on the setup can be found here: Octopress setup. Run this through your console:

1
2
3
4
5
6
7
git clone git://github.com/imathis/octopress.git octopress
cd octopress
bundle exec rake install
bundle exec rake new_post["first post"]

# and start up the server
bundle exec rake preview

You should see the blog up and running if you punch in http://localhost:4000 in your browser:

Setting up the S3 bucket (as a static site)

Amazon is able to host static sites directly through the S3 buckets they provide. You’re going to want to add a bucket with the name of ‘www.yourdomain.com’. Then click on the properties, enable website static hosting, and set the index document to ‘index.html’.

Setting up s3cmd

I’m going to use s3cmd to upload our site to S3, this will allow us to push the site up through a rake task (and do some heavy lifting for us). I would normally suggest installing s3cmd through brew, but in this case we need the ability to invalidate our cloudfront cache, and the brew version doesn’t seem to support that flag currently. You can install s3cmd directly through source by running this:

1
2
3
4
git clone https://github.com/s3tools/s3cmd s3cmd
cd s3cmd
sudo python setup.py install
s3cmd --configure

You’ll have to enter your S3 API keys when prompted (your Access Key ID and Secret Access Key), you can find them here:

It should end up writing a file in ~/.s3cfg which contains your amazon credentials. This will allow you to use s3cmd from the deploy rake task that we’ll build.

Deploy to Amazon S3 static site

There’s a great rake task located here that we’ll leverage. Paste this at the bottom of your Rakefile:

1
2
3
4
5
desc "Deploy website via s3cmd with CloudFront cache invalidation"
task :s3 do
  puts "## Deploying website via s3cmd"
  ok_failed system("s3cmd sync --acl-public --reduced-redundancy --cf-invalidate public/* s3://#{s3_bucket}/")
end

Within the Rakefile you’ll need to setup a few variables:

1
2
3
4
5
# find deploy_default = "rsync" and replace it with 
deploy_default = "s3"

# and then add this line underneath it
s3_bucket = "www.yourdomain.com"

This will set our default deploy method to the s3 task that we added to the bottom, and define the bucket that the rake task needs.

Let’s deploy!

1
2
bundle exec rake generate
bundle exec rake deploy

All of your files should be pushed up to your Amazon S3 bucket and you should be able to visit the endpoint that was defined on your bucket.

www.ryanonrails.com.s3-website-us-east-1.amazonaws.com would be my endpoint

Configuring Cloudfront

We want this site to be very fast, by pushing out our static items to CloudFront we can gaurantee a faster load time than our regular S3 bucket. I saw improvements anywhere from .5-1s speed increases (considering the site takes 2s to load on the regular S3 bucket, it’s quite a large percentage). It can speed up your site from 25-50%.

Let’s head back over to Amazon CloudFront and create a distribution. Click Create Distribution, Choose Download for the next step. Now here comes the tricky part. In the Domain Name box, make sure to enter your Endpoint URL (IE: www.ryanonrails.com.s3-website-us-east-1.amazonaws.com). The box will auto complete to your bucket, but not the actual custom origin that you have setup with your static site. In the Alternate Domain Names(CNAMEs) box, enter in ‘www.yourdomain.com’. You can leave everything else as default.

Here’s what it should look like once you’ve created your distribution:

And if you select it and click edit, the General and Origins tab:

We add the CNAME so when a request comes in for www.ryanonrails.com it can match the url’s up properly. This will make more sense when we setup our DNS.

It will take about 10-15 minutes to distribute across the globe. Once it’s finished you should be able to visit your site through your CloudFront Domain Name (not to be mistaken with ‘www.yourdomain.com’). IE: http://d231akc98dz4lc.cloudfront.net/index.html (which will show you the index page of my blog) or http://d231akc98dz4lc.cloudfront.net/blog/archives/ (my archive).

Updating your DNS settings

We’ll need to change up our DNS settings to make sure that www.yourdomain.com now points to the CloudFront Domain Name. You’ll need to set your A Record to 174.129.25.170 and create a www CNAME that points to your Cloudfront Domain Name. Here’s my setup on GoDaddy:

By pointing our A record to 174.129.25.170 it actually leverages a service called WWWizer which takes our domain ‘yourdomain.com’ and redirects it to ‘www.yourdomain.com’. The reason we have to do this is because you can’t actually point an A record at a URL like you can a CNAME, but we need a way that if you hit ‘yourdomain.com’ it takes you to the www version of the site. More information on this here.

At this point if someone requests www.ryanonrails.com/index.html it sends it to clou

Cloudfront cache invalidation

By default in our rake task we pass in --cf-invalidate to s3cmd. This will invalidate any of the files that are out of date on our blog. This is useful since we generally want to see our blog post up and live once we post. You can monitor the invalidation job in the Invalidations tab in CloudFront:

Example invalidation

Once it finishes you should be able to reload ‘wwww.yourdomain.com’ and see your latest blog post (or typo fix ;)).

Potential problems

I ran into a few problems while setting this all up. The first was that I named my bucket ‘ryanonrails.com’ without the www., this caused problems once I implemented the WWWizer service and it ended up redirecting to a bucket that didn’t exist (‘www.ryanonrails.com’ at the time). Another problem was that I set a Default Root Object on my CloudFront distribution. This broke any sub directories (such as ‘www.ryanonrails.com/blog/archives’). From what I understand, this would be used on an S3 bucket that wasn’t set up as a static site.

References:

I haven’t been blogging for the past year or so, and I hope to change that soon. I’ve been writing down topics for the past few months, so I plan to pull from that pool for the next while or so.

Technology wise, I decided to drop Wordpress. A couple of friends have had luck with jeykll, octopress and nanoc. I ended up choosing octopress, since it has a bunch of beautiful layouts that come along with it.

I also decided on ditching my old host (http://bluehost.com) and moved over to Amazon S3 & Cloudfront. The site is blazing fast now. There are a few tweaks I still need to do (compress assets, html crunch, clean up about page), but I think it should suffice for now.

Here’s the old blog layout:

And the new (which of course you’re looking at ;) ):

Ry

Here’s some example code for MVC 3 & 4 unit tests. Using Ninject/Moq/Nunit/Repositories

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using EST.Controllers;
using EST.Models;
using Moq;
using System.Web.Mvc;

namespace EST.Tests
{
    [TestFixture]
    public class ComplexitiesControllerTest
    {
        private Mock complexityRepoMock;
        private Mock complexityTypeRepoMock;
        private Mock analystTypeRepoMock;
        private ComplexitiesController complexityRepo;

        public AnalystType analystProg;
        public ComplexityType complexityVerySimple;

        [SetUp]
        public void Setup()
        {
            // initial arrange
            complexityRepoMock = new Mock();
            complexityTypeRepoMock = new Mock();
            analystTypeRepoMock = new Mock();
            complexityRepo = new ComplexitiesController(complexityTypeRepoMock.Object, analystTypeRepoMock.Object, complexityRepoMock.Object);

            // Create Analyst Types
            AnalystType analystProg = new AnalystType { Name = "Programmer Analyst" };

            // Create Complexity Types
            ComplexityType complexityVerySimple = new ComplexityType { Name = "Very Simple" };
        }

        [Test]
        public void IndexTest()
        {
            // arrange
            var complexitys = new List
            {
                new Complexity
                {
                    AnalystType = analystProg,
                    ComplexityType = complexityVerySimple,
                    Area = "Design and Architecture",
                    Effort =
                },

                new Complexity
                {
                    AnalystType = analystProg,
                    ComplexityType = complexityVerySimple,
                    Area = "Stored Procedure",
                    Effort =
                },

                new Complexity
                {
                    AnalystType = analystProg,
                    ComplexityType = complexityVerySimple,
                    Area = "Data Access Services",
                    Effort = 0.5
                }
            };

            complexityRepoMock.Setup(a => a.AllIncluding(complexity => complexity.ComplexityType, complexity => complexity.AnalystType)).Returns(complexitys.AsQueryable());

            //act
            var result = complexityRepo.Index() as ViewResult;
            var model = result.ViewData.Model as IQueryable;

            //assert
            Assert.AreEqual(model.Count(), 3);
        }

        [Test]
        public void DetailsTest()
        {
            // arrange
            Complexity complexity = new Complexity()
            {
                ComplexityId = 1,
                AnalystType = analystProg,
                ComplexityType = complexityVerySimple,
                Area = "Design and Architecture",
                Effort =
            };
            complexityRepoMock.Setup(a => a.Find(1)).Returns(complexity);

            // act
            var result = complexityRepo.Details(1) as ViewResult;
            var model = result.ViewData.Model as Complexity;

            // assert
            Assert.AreEqual(model.ComplexityId, 1);
        }

        [Test]
        public void CreateTest()
        {
            // act
            var result = complexityRepo.Create() as ViewResult;

            // assert
            Assert.That(result, Is.Not.Null);
        }

        [Test]
        public void CreatePostTest()
        {
            // arrange
            Complexity complexity = new Complexity()
            {
                ComplexityId = 1,
                AnalystType = analystProg,
                ComplexityType = complexityVerySimple,
                Area = "Design and Architecture",
                Effort =
            };

            var submittedComplexity = new List();
            complexityRepoMock.Setup(z => z.InsertOrUpdate(complexity)).Callback((Complexity a) => submittedComplexity.Add(a));

            //act
            var result = complexityRepo.Create(complexity) as ViewResult;

            // assert
            Assert.AreEqual(submittedComplexity.Count, 1);
        }

        [Test]
        public void CreatePostFailTest()
        {
            // arrange
            Complexity complexity = new Complexity()
            {
                ComplexityId = 1,
                AnalystType = analystProg,
                ComplexityType = complexityVerySimple,
                Area = "Design and Architecture",
                Effort =
            };

            var submittedComplexity = new List();
            complexityRepoMock.Setup(z => z.InsertOrUpdate(complexity));

            //act
            var result = complexityRepo.Create(complexity) as ViewResult;

            // assert
            Assert.AreEqual(submittedComplexity.Count, );
        }

        [Test]
        public void EditTest()
        {
            // arrange
            Complexity complexity = new Complexity()
            {
                ComplexityId = 1,
                AnalystType = analystProg,
                ComplexityType = complexityVerySimple,
                Area = "Design and Architecture",
                Effort =
            };

            complexityRepoMock.Setup(z => z.Find(1)).Returns(complexity);

            //act
            var result = complexityRepo.Edit(1) as ViewResult;
            var model = result.ViewData.Model as Complexity;

            // assert
            Assert.AreEqual(model.ComplexityId, 1);
        }

        [Test]
        public void EditPostTest()
        {
            // arrange
            Complexity complexity = new Complexity()
            {
                ComplexityId = 1,
                AnalystType = analystProg,
                ComplexityType = complexityVerySimple,
                Area = "Design and Architecture",
                Effort =
            };

            complexity.Area = "Design";

            var submittedComplexity = new List();
            complexityRepoMock.Setup(z => z.InsertOrUpdate(complexity)).Callback((Complexity a) => submittedComplexity.Add(a));

            //act
            var result = complexityRepo.Edit(complexity) as ViewResult;

            // assert
            Assert.AreEqual(submittedComplexity.First().Area, "Design");
        }

        [Test]
        public void DeleteTest()
        {
            // act
            var result = complexityRepo.Delete(1) as ViewResult;

            // assert
            Assert.That(result, Is.Not.Null);
        }

        [Test]
        public void DeletePostTest()
        {
            // arrange
            Complexity complexity = new Complexity()
            {
                ComplexityId = 1,
                AnalystType = analystProg,
                ComplexityType = complexityVerySimple,
                Area = "Design and Architecture",
                Effort =
            };

            var submittedComplexity = new List();
            submittedComplexity.Add(complexity);

            complexityRepoMock.Setup(z => z.Delete(1)).Callback(() => submittedComplexity.RemoveAt());

            //act
            var result = complexityRepo.DeleteConfirmed(1) as ViewResult;

            // assert
            Assert.AreEqual(submittedComplexity.Count, );
        }
    }
}

I ran into this error again. I think I’ve got it all figured out. Here’s the excerpt from the log:

Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: An exception occurred when executing the plugin. Error: One or more data source credentials required to run the report have not been specified. —> Microsoft.ReportingServices.ReportProcessing.ReportProcessingException: One or more data source credentials required to run the report have not been specified.

My current setup is this. I have regular MSCRM_FetchDataSource reports using Credentials supplied by the user running the report. I’m currently running a plugin when a a drop down list value has changed. This plugin runs an SSRS report and drops it into sharepoint.

The error actually stems from the fact that the username and password being passed to SSRS from the plugin isn’t getting populated. The SRS data connector that you install for CRM passes these values back and for you for the out of box reports. For whatever reason, this code will not populate those fields:

1
return ReportService.RenderReport(reportUrl, _networkCredential, reportPath, parameters, "PDF", devInfo, "en-us");

In this situation I’ve found the best course of action is to set your data source as follows:

MSCRM_FetchDataSource
Credentials stored securely in the report server
User:-username-
Password:-password-
Use as Windows credentials when connecting to the data source CHECKED
Impersonate the authenticated user after a connection has been made to the data source NOT CHECKED

We use 1 main account for our reports so this works out well. This will allow plugins to access SSRS and allow the out of box reports to run. All while only having to use 1 datasource (we previously had the custom reports on 1 datasource, and the rest of CRM on MSCRM_FetchDataSource).

I recently ran into this issue when I was accessing my WEBapi controller. I’m actually using MVC4, but I have ran into the same error in both MVC3 and MVC4.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
System.InvalidOperationException

An error occurred when trying to create a controller of type 'EST.Controllers.API.TemplatesController'. Make sure that the controller has a parameterless public constructor.


at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpControllerContext controllerContext, Type controllerType)
 at System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateInstance(HttpControllerContext controllerContext, HttpControllerDescriptor controllerDescriptor)
 at System.Web.Http.Dispatcher.DefaultHttpControllerFactory.CreateController(HttpControllerContext controllerContext, String controllerName)
 at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncInternal(HttpRequestMessage request, CancellationToken cancellationToken)
 at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)


System.ArgumentException

Type 'EST.Controllers.API.TemplatesController' does not have a default constructor


at System.Linq.Expressions.Expression.New(Type type)
 at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)
 at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpControllerContext controllerContext, Type controllerType)

Here’s the actual code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace EST.Controllers.API
{
    public class TemplatesController : ApiController
    {
        private readonly ITemplateRepository templateRepository;

        public TemplatesController(ITemplateRepository repository)
        {
            this.templateRepository = repository;
        }

        //
        // GET: /api/Templates/

        public IQueryable Get()
        {
            return templateRepository.All;
        }
    }
}

The error message is slightly misleading. The actual error was that I had forgotten to map out my injection via Ninject in /App_Start/NinjectWebCommon.cs

1
2
3
4
private static void RegisterServices(IKernel kernel)
{
    kernel.Bind().To();
}

Once I did this the TemplateRepository was able to be instantiated and move forward. Hopefully this helps someone.

I ran in to this error:

Uncaught TypeError: Cannot call method ‘dispatch’ of undefined

The first thing to check is that your route exists. I created a utility located here: https://github.com/RyanonRails/batman.utilitybelt that can list out your current routes.

If the route exists, you need to make sure that your controller names are named correctly as such:

1
2
3
4
5
@resources 'sections', 'sectionrows'

-------------This would looks for these 2 controllers------------
class EST.SectionsController extends Batman.Controller
class EST.SectionrowsController extends Batman.Controller

I ran into this because of the above 2 word model. For future reference here’s the layout I used:

Driver (/est.coffee):

1
2
3
4
5
6
window.EST = class EST extends Batman.App
  Batman.ViewStore.prefix = 'app/views'
  @controller 'sectionrows'
  @model 'sectionrow'

  @resources 'sectionrows'

Controller (/controllers/sectionrows_controller.coffee):

1
2
3
4
5
6
class EST.SectionrowsController extends Batman.Controller
  routingKey: 'sectionrows'

  index: ->
    EST.SectionRow.load (err,results) =>
      @set 'sectionrows', results

Model (/models/sectionrow.coffee):

1
2
3
4
5
6
7
class EST.SectionRow extends Batman.Model
  @resourceName: 'sectionrow'
  @url = "/api/sectionrows"

  @set 'primaryKey', 'SectionRowId'
  @persist Batman.RestStorage
  @encode 'SectionRowId', 'WorkType'

View (/views/sectionrows/index.html):

1
2
3
4
5
6
7
8
<h2>All Section rows</h2>

  <div data-foreach-section="sectionrows" data-mixin="animation">
    <a data-bind="sectionrow.SectionRowId" ></a>
    <p data-bind="sectionrow.WorkType"></p>
  </div>

Total # of sections: <span data-bind="sectionrows.length"></span>

Batman 0.9

I couldn’t figure out why my data wasn’t being submitted up to the server on a POST (create). Turns out that the data-bind’s are case sensitive. IE:

1
2
3
4
5
6
class EST.Section extends Batman.Model
  @resourceName: 'section'

  @set 'primaryKey', 'SectionId'
  @persist Batman.RestStorage
  @encode 'SectionId', 'Name'

They need to match up with @encode ‘SectionId’, ‘Name’

1
2
<form id="new_section" data-event-submit="create" data-formfor-section="section">
  <input type="text" placeholder="Section Name" data-bind="section.Name"/>

The POST parameters came across once I specified them as case sensitive.

Batman 0.9

If you’re trying to get batman.js trying to run within visual studio & IIS 7.5 you’re going to run into some issues serving up coffeescript files to batman.

The error might look something like this:

Failed to load resource: the server responded with a status of 404 (Not Found)

From what I understand, IIS doesn’t know what type of MIME type coffeescript is, so it doesn’t serve it out, here’s what you need in your web.config for it to work properly (put in my whole web.config):

1
2
3
4
5
6
7
8
9
10
11
12
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0"/>
  </system.web>

  <system.webServer>
    <httpErrors errorMode="Detailed" />
    <staticContent>
      <mimeMap fileExtension=".coffee" mimeType="coffeescript" />
    </staticContent>
  </system.webServer>
</configuration>

I gleaned some information from this SO article.

Thanks,
Ry

I’ve just started using EntityFramework.Migrations and came accross this error:

No pending explicit migrations.
Applying automatic migration: 201205101614472_AutomaticMigration.

Automatic migration was not applied because it would result in data loss.

It’s because my migrations would’ve nuked some of my data. I’m okay with that though, you just need to throw on the -Force tag to get it to complete the migration:

Update-Database -Verbose -Force