Rusty Divine

Live, Love, Learn, Teach

VS2012 Multi-Project Solution References Error

While working on a plugin for nopCommerce (a payment plugin for Sage Payments, the USA portal, HTTPS), I was getting build errors for references to Nop.Core and Nop.Services.

Error	5	The type or namespace name 'Core' does not exist in the namespace 'Nop' (are you missing an assembly reference?)	C:\Code\SgtNop\Main\Plugins\Nop.Plugin.Payments.SageHttps\SageHttpsPaymentProcessor.cs	8	11	Nop.Plugin.Payments.SageHttps

 

The intellisense was working on Nop's assemblies, but the project wouldn't compile. The problem was my new plugin project was compiling to .Net 4 when the Nop.Core compiles to .Net 4.5. After changing the plugin's target framework to 4.5, everything compiled.

 

CakePHP with IIS, SQL Server, SRS, LDAP, and TFS

Our development team recently completed a project with a requirement that PHP be used and hosted on IIS 7. We are a C#.Net team and have some experience with PHP and we had to work hard to get all of our tools to work together, so hopefully this will help you, too. The project turned out fantastically, thanks in part to a really good product owner on the client side. Thanks goes to Adam Costenbader for some of the notes for these steps.

  1. Install IIS 7 (add/remove programs > configure windows features)
  2. From the IIS Manager, enable FastCGI support.
  3. Download and install PHP 5.3 or later
  4. Install the URL Rewrite extension
  5. Install the PHP Manager
    1. Enable php_pdo_sqlsrv_54_nts.dll for sql server. If missing, you can download it from Microsoft, then install and enable it by adding an extension in the PHP manager.
    2. Enable php_LDAP.dll for LDAP access
  6. In IIS Manager, check that there is a handler mapping for PHP to the FastCGIModule. With the server node selected, enter the Handler Mappings and if *.php is not setup for PHP53_via_FastCGI, then add the mapping. The path is *.php, module is FastCgiModule, executable is C:\[php path]\php-cgi.exe, name is PHP53_via_FastCGI. Select the Request Restrictions and then check Invoke and select File or Folder.
  7. Create a website in IIS Manager and set index.php as the default document for the website.
    1. The security for the root folder needs to permit USERS at the basic level, and IIS_IUSRS needs full permissions to the app\tmp folder.
  8. Install the TFS Power Tools for VS2012 to get a Windows Explorer add-in for TFS
  9. For reporting, install the SQL Server Data Tools
  10. For PHP Intelli-sense, we purchased PHP Tools for Visual Studio
  11. We were never able to get debugging to work with CakePHP, although we tried PHP Tools and Xdebug.
  12. To make the solution work with TFS, we had to make sure the app\tmp directory wasn’t read-only, but the folder structure had to be there. We had trouble with the project trying to add the files back in each time, so we ended up just excluding the app\tmp from source control and then creating the folder structure manually on new checkouts.
  13. To get some SQL Server Reporting Services to serve reports as HTML into a CakePHP view:
    1. We created a local user on the report server and permissions (db_datareader) to the database.
    2. If SRS is on a different server, you need to allow basic authentication by editing the rsreportserver.config found in the Program Files:
      1. <Authentication>
           <AuthenticationTypes>
            <RSWindowsNTLM/>
            <RSWindowsBasic/>
           </AuthenticationTypes>
           <EnableAuthPersistence>true</EnableAuthPersistence>
        </Authentication>
    3. On the report server, run IE as an administrator and browse to the server/reports folder. Navigate to your reports folder and to the Properties tab > Security page. Add the local user here and make sure Browser is checked.
    4. For more examples, see this MSDN post.

We were able to get this CakePHP website running on an Azure website, too, which was a fun challenge (we did not activate the LDAP or SRS portions for this). This was our web.config for Azure:

<!-- Configuration for Windows Azure -->
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <clear/>
        <rule name="Imported Rule 0" stopProcessing="true">
          <match url="^(img|css|files|js)(.*)$"/>
          <action type="Rewrite" url="app/webroot/{R:1}{R:2}" appendQueryString="false"/>
        </rule>
        <rule name="Imported Rule 1" stopProcessing="true">
          <match url="^(.*)$" ignoreCase="false"/>
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
          </conditions>
          <action type="Rewrite" url="index.php?url={R:1}" appendQueryString="true"/>
        </rule>
        <rule name="Imported Rule 2" stopProcessing="true">
          <match url="^$" ignoreCase="false"/>
          <action type="Rewrite" url="/"/>
        </rule>
        <rule name="Imported Rule 3" stopProcessing="true">
          <match url="(.*)" ignoreCase="false"/>
          <action type="Rewrite" url="/{R:1}"/>
        </rule>
        <rule name="Imported Rule 4" stopProcessing="true">
          <match url="^(.*)$" ignoreCase="false"/>
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
          </conditions>
          <action type="Rewrite" url="index.php/{R:1}" appendQueryString="true"/>
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>
<!-- Configuration for Windows Server 2008 --> 
<?xml version="1.0"?>
<configuration> 
  <system.webServer>
    <rewrite>
      <rules>
        <clear/>
        <rule name="Imported Rule 0" stopProcessing="true">
          <match url="^(img|css|files|js)(.*)$"/>
          <action type="Rewrite" url="app/webroot/{R:1}{R:2}" appendQueryString="false"/>
        </rule>
        <rule name="Imported Rule 1" stopProcessing="true">
          <match url="^(.*)$" ignoreCase="false"/>
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
          </conditions>
          <action type="Rewrite" url="index.php?url={R:1}" appendQueryString="true"/>
        </rule>
        <rule name="Imported Rule 2" stopProcessing="true">
          <match url="^$" ignoreCase="false"/>
          <action type="Rewrite" url="app/webroot/"/>
        </rule>
        <rule name="Imported Rule 3" stopProcessing="true">
          <match url="(.*)" ignoreCase="false"/>
          <action type="Rewrite" url="app/webroot/{R:1}"/>
        </rule>
        <rule name="Imported Rule 4" stopProcessing="true">
          <match url="^(.*)$" ignoreCase="false"/>
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
          </conditions>
          <action type="Rewrite" url="index.php?url={R:1}" appendQueryString="true"/>
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
  <system.web>
    <compilation targetFramework="4.5"/>
    <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
  </system.web>

   <system.net >
    <mailSettings>
        <smtp deliveryMethod="SpecifiedPickupDirectory" from="from@me.com">
        <specifiedPickupDirectory pickupDirectoryLocation="c:\Temp\MailDrop" />
      </smtp>-
    </mailSettings>
  </system.net>
  
</configuration>

Book review analogy

Sometimes I encounter customers who are surprised at the effort that it takes to create custom software. Some of these customers are very good at understanding systems and big pictures and are uncomfortable with details. Some people can do both, but I find that to be welcome rarity.

A recent customer really struck me as someone who I could have helped with the following analogy, had I had the foresight.

The customer explained the project in a twenty minute conversation where I asked some questions that he agreed were things he hadn’t thought about. When I explained our requirements gathering process, which we charge a flat fee for, he was fine, but within a week he responded via email to express his frustration that we would charge him to develop a design. His email was worded rather strongly, but that was the gist of it.

I don’t think there will be a middle ground for us, but I wonder what I can do to help customers new to professional custom software development to understand it better. That’s when this analogy occurred to me:

This initial meeting has helped me understand your project at the same depth as reading a decent book review on Amazon. I know I’m interested in it, I know I’d like to read it, and I know the general plot, but I don’t know how many pages it has or a single line of its dialog. I’m not sure what the cover art looks like or who all the characters are. I’d like to setup another meeting with you where we will try to brainstorm more of these details, narrow our cast and focus on what really is important for the first book in what may become a series. I’ll take these notes and spend a significant amount of time developing them further, making sure no one else has already written this book, and then come back to you with all the notes, designs, research, and a fixed price quote to write this book for you. If you decide its not worth it at that point, or that someone else will write it better or cheaper than I can, you’re free to take these designs and have someone else write your book.

Breaking the 1000ms Time-To-Glass mobile barrier

Ilya Grigorik is one of Google's engineers who is on the Make the Web Fast team. His talk on Breaking the 1000ms Time to Glass Mobile Barrier has some great tips:

Optimize Images:

 

This may mean making jpgs instead of pngs.

Mobile Latency:

 

The time it takes to send that first packet can eat up half-a-second!

Async scripts:

 

  Performance Rules

 

 

 

 Implications

 

 

 Bottom Line

One Request. Inline. Defer the rest.

2013 WASP-B Trapshoot League Schedule

2013 WASP-B Schedule

Here is the 2013 WASP-B schedule. You can come shoot at any one of these even if that’s the only shoot you decide to try.

April 7: Nebraska City

April 21: Valley

May 5: Ashland

June 2: Lincoln T&S

July 7: Papillion

August 18: Bellevue

September 15: Finals at Nebraska City

All club shoots start at 8am and close at 3pm. Finals start at 8am and close at 2pm.

Nebraska Code Camp 3

This year at Nebraska Code Camp for the first time there was an extra day of hands-on labs. I signed up for Advanced Machine Learning and a Single Page App (SPA) lab that was cancelled at the last minute, so instead I crashed Adam Grocholski's Windows 8 lab where we had a lot of fun just playing around.

I'm really proud to work for Five Nines Technology Group who was a Platinum Sponsor this year - we are really excited about the programming community here in Nebraska and enjoy contributing to its vibrancy.

 

Machine Learning Notes

My favorite part of labs are always the great resources for continued learning I get from the instructors. I took the machine learning lab because it was out of my comfort zone, but it is something that I find could be quite useful. For instance, a potential customer recently asked us to write an algorithm that compared athletes across the nation and rank them by some test results.

So, here are the resources Luke Amdor shared with us:

Some of the topics he covered were:

 

Windows 8 Notes

This was a full-day lab, but I only caught the last half. The first half they did some hands-on labs at MSDN; here are some example labs you can do.

We took a look at many of the Azure offerings and talked about differences between mobile services and cloud services and networking and active directory. I totally encourage you to sign up for a free 90-day trial!

We also had a lot of fun with game programming. Adam's favorite is TouchDevelop - a really cool game and app programming tool that is free and lets you share code snips. 

How To Set a Modified Date in Entity Framework

Just saw Julie Lerman show a slick way to set the modified date on an entity by overriding the SaveChanges() on a DbContext:

 

 

Other good tips:

  • Download the EF PowerTools for a nice plug in that lets you rt-click on the class that implements DbContext and select EF\View Entity Data Model (read only) => to get a relational diagram of how EF is going to create your database before you do a migration.

 

  • In your models, use both the navigation property and the foreign key to increase performance (w/out FK, EF has to go figure out what ID to put in there), to make some object graph management more intuitive for adding/updating or just figuring out if that navigation property exists without invoking lazy loading.

 

  • For lookup-lists, you can improve performance by not tracking the entity state:

_context.MyEntity.AsNoTracking().OrderBy(a=>a.Name).ToList();

When you do the AsNoTracking, combine it with the previous tip so that EF doesn't add a new MyEntity when you save the parent each time:

parent.MyEntityId = Id; // instead of parent.MyEntity = myEntity <- that might cause EF to save a new (duplicate) myEntity to the database

 

Subtle MVC, Razor, Membership Bug

I encountered a really frustrating bug yesterday when I tried to hit my MVC project on the QA server, and it turns out it manifested itself in several telltale ways:

  1. The QA server (IIS 7) reported 403 Forbidden for my login page.  Could not load anything.
  2. My local machine (IIS 7 Express) would not show the ValidationSummary on the login page
  3. My local machine would not let me navigate to the forgot password page, or any [Allow Anonymous] pages other than the login page, unless I logged in;
  4. after logging into my local machine, and then everything worked fine, and I could get to the [Allow Anonymous] pages
  5. My local machine would not show the company name text in the banner until I logged in

The last sign was finally what clicked – I didn’t realize these all were related until I noticed that one.  On my _layout.cshtml page, I have the following:

@{ Html.RenderAction("_CompanyName", "CompanyName"); }

The site is a multi-tenant application that has a url like: {company}.domain.com.  The above calls into an action that takes that {company} and looks up the company name in the repository, then displays that name in the banner.

The problem was the _CompanyName action on the CompanyNameController was not marked as [Allow Anonymous].  IIS Express was able to let this slide, but IIS did not!

#HDC12–Building a Dream Team

This afternoon I attended the Build a Dream Team hands-on lab presented by Chris Carlson and Gabe Romero of Aureus Group.  They presented tips on how to hire and retain great team members.  We’re currently looking for some top talent at Five Nines, so the timing was great.

I learned that we could improve our interview process by creating a performance profile that focuses on what the candidate will have to do to succeed in the job.  What will be the objectives?  What projects will they work on?  What responsibilities will they be assigned? How long will they have to reach each objective?  Defining the future of what they are going to need to do and making sure they are qualified to do that is more important than arbitrarily specifying that they need XYZ certification or a degree in ABC.

For the first hour we talked about hiring and the book “Hire With Your Head” by Lou Adler.  Chris was a big fan of this guy’s work, which I haven’t read before, but a lot of the tenants she talked about from his work rang true for me, too.  For example, when writing an ad for a job, focus on what the candidate will have to do, not what experience they have to already have.  Make the candidate a customer – try to sell them on your company, and make sure they leave with a positive experience even if they don’t get an interview.  Try to limit bias and emotions by asking the same narrow, quantitative type questions to each candidate, and then scoring them on some pre-defined categories (having the book would help here, it comes with templates and extras).  Also, be careful of initial reactions to a candidate – it may be best to take a 30min break before you talk to anyone about the evaluation of the candidate.  Concentrate on a candidate’s past performance – what have they done to improve the environment at past jobs?  If nothing, then don’t expect them to hit the high notes in the future, either. 

When checking references, validate the candidate’s strengths with specific examples.   Would that reference hire them or work with them again?  How does the candidate compare to others they know at the same level?

The next hour or two we talked about accountability and engagement.  Gabe described the difference between responsibility and accountability by explaining that responsibilities are assigned, or given to you, but only you can be accountable to get the results done.  He talked about how engaging with your team is critically important to help understand what they are experiencing, what are their frustrations and aspirations and goals, and to give feed back and reinforcement.

I think our AppDev group is doing a very good job of accountability and engagement.  We practice an agile approach to all of our work, and each of us is held accountable each day at our daily stand-up meeting where we quickly review what we said we were going to get done yesterday, what got done, and what we’re doing today.  You can see instantly that someone got off track, and no one wastes more than half a day going down a rabbit hole before they get a chance to come up for some air and help from the team.  Our iterations are time-boxed, so it is obvious at the end of the 2-weeks whether we got done what we had planned or not.  After each iteration, we do a retrospective (Good/Could be better/Improvements) that has proven to be such a powerful agent of change that I’ve been thinking about how to apply it to my personal life.

We have weekly one-on-one meetings with our Director where we talk about whatever is going on with us in the environment.  It’s a great chance to vent (constructively, of course) and get some feedback.  We build trust as a team because we know our opinions matter and we really are being listened to. 

We occasionally have strategy meetings where we talk about the course of our group and what direction we will concentrate on in the future.  Each of us brings our ideas to the table during those meetings, and all thoughts are welcome.

#HDC12–Building Win8 Apps with JavaScript

I’d like to thank HDC12, Jeff Brand and Matt Milner for a great hands-on lab today on building Win8 apps with JavaScript.  We worked through a demo project that queried Twitter for tweets based on a search string, then presented the results in a nice grid.  Each cell in the grid had the author’s picture and the tweet.

Jeff made the demo project available via Git: https://github.com/spartyspartan/TweetScan

Resources on Win8: http://goo.gl/Wu4NH

Here are a few things you need to know about developing a win8 RT app on the JS stack (some of these would apply to a xaml app on WinRT, too):

  1. You can't reference js from a CDN or internet; has to be local.  The app has to be able to run disconnected, and has to be run in one security context
  2. In un-snapped view, the app layout needs to scroll horizontally, not vertically
  3. The app is suspended when it is not visible.  After a while, if resources get low, Win8 will terminate your app and not tell you! So, on receiving the suspend event, assume you are/will be terminated because there is no event for terminated and go ahead and save state or whatever you need to do.
  4. You have to have win8 & vs12 to develop the apps – they use WinJs which relies on WinRT
  5. The app has to support snap view – when the app gets snapped to the side.  At that point, it needs to either scroll vertically or handle the change gracefully.  For instance, a game might just put up a “paused” screen in that case.
  6. The most common architecture will probably be a single-page-app.  You can use js namespaces to avoid script collissions.
  7. Make sure to check the project’s manifest in the package settings to set the capabilities and available declarations so that the app can access more than just the Internet.
  8. Blend visual designer is definitely worth checking out.  It renders the app in an engine that includes a javascript sandbox.
  9. You can hook into the Search/Share/Settings charms to set up how your app will interact with these
  10. You can add custom buttons to the app bar – be sure to check the metro design guidelines for where to put global vs context-sensitive tools.
  11. The app store reviews all apps.  If you are selling yours, there is a tiered pricing structure starting at $1.99.  MS takes 30% of sales up to $25k, and 20% after.  If you don’t sell the app, it can be added to the store for free and MS provides advertising tools (or you can use others), and you can still use a payment gateway in the app without having to pay MS.  So, the only time you pay MS is if the app is for sale.  There are very easy ways to make it a trial software for 7/14/30 days (e.g.) and MS will handle users trying to trick the trial by uninstall/reinstall or other means.
  12. When an app is off-screen, it gets 0 CPU.  A device can have up to 7 apps that are running background processes (think email, IM), and the user will choose which of their apps win if there are >7, so don’t assume your background polling process will be running if your app is suspended.  You can also do live tiles for the start screen that use push notifications or toast notifications, and this is a free service that MS provides.  For some rare cases, like a skype app, there are ways to keep a connection open even if the device is locked.
  13. You can have multiple tiles for one app – think a separate tile for each stock you are tracking in the financial app.