Search

Categories

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Send mail to the author(s) E-mail

# Monday, 08 August 2011

image

Code Snippet
// MVC3 looks in routedata, querystring
        // C#4 default parameter of *
        public ActionResult Search(string name = "*")
        {
            //var name = RouteData.Values["name"];
            name = Server.HtmlEncode(name); // Content doesn't htmlencode
            return Content(name);
            //return Content("You have reached the cusine controller");
        }

redirecting to a route

Code Snippet
// MVC3 looks in routedata, querystring, posted form values
        // C#4 default parameter of *
        public ActionResult Search(string name = "*")
        {
            if (name == "*") {
                //return RedirectToAction("Search", "Cuisine", new { name = "french" });
                return RedirectToRoute("Cuisine", new { name = "german" });
            }
            //var name = RouteData.Values["name"];
            name = Server.HtmlEncode(name); // Content doesn't htmlencode
            //return RedirectPermanent("http://www.programgood.net");
            //return RedirectToAction("Index", "Home");
            return Content(name);
            //return Content("You have reached the cusine controller");
        }

returning a file;

image

Json:

image

| | # 
# Sunday, 07 August 2011

problem – using my version of EFCodeFirst this isn’t compiling.

Code Snippet
        public void MarkAsModified(object entity) {
            base.ObjectContext.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
        }

Here is the new working CTP5 version of the code.

Code Snippet
public int Save(Person person) {
            //if (person.PersonID == 0) {
            //    db.People.Add(person);
            //}
            //else {
            //    //var personRetrived = db.People.Find(person.PersonID);
            //    db.People.Attach(person);
            //    //db.MarkAsModified(person); // chaged with EF Code First CTP5.
            //}

            db.Entry(person).State = person.PersonID == 0 ?
                EntityState.Added :
                EntityState.Modified;
            
            db.SaveChanges();
            return person.PersonID;
        }

image

Automatically creating unit tests from our controller.

Constructor Injection

Code Snippet
public class PersonController : Controller {
        // constructor injection
        IPersonRepository repo;
        public PersonController(IPersonRepository repository) {
            repo = repository;
        }

        public PersonController() {
            repo = new PersonRepository();
        }


        public ActionResult Index() {
            var people = repo.GetAll();
            return View(people);
        }

Installing ninject.mvc3

Code Snippet
private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<IPersonRepository>().To<PersonRepository>(); // DM put this in
        }   

then in controller don’t need the parameterless contructor:

Code Snippet
public class PersonController : Controller {
        // constructor injection
        IPersonRepository repo;
        public PersonController(IPersonRepository repository) {
            repo = repository;
        }
| | # 
# Saturday, 06 August 2011

NuGet installed EntityFramework and then SQLCE.

image

Had to type own code first Poco, and showing EF and SqlServerCe

Rename MyProductContect to ProductContext – just do it and press ctrl . (instead of F2)

image

Did full CRUD using EF Code First and SqlCE.

| | # 
# Saturday, 16 July 2011

From asp.net/mvc videos

Shift Alt C to create a new class

Extension method syntax

image

    public static class HtmlHelpers
    {
        public static string Truncate(this HtmlHelper helper, string input, int length)
        {
            if (input.Length <= length)
                return input;
            else
                return input.Substring(0, length) + "...";
        }
    }

In the view:

@using RazorHelpers.Helpers
 
<h2>@Html.Truncate(ViewBag.Message as string,8)</h2>
image

could add namespace into the web.config so don’t need to add a ref in the using.

This didn’t work!

Razor Declarative Syntax

@helper Truncate(string input, int length)
{
        if (input.Length <= length) {
             @input
        } else  {
             @input.Substring(0, length)<text>...(razor)</text>     
        }
}
<h2>@Truncate(ViewBag.Message as string,8)</h2>
Once have got that working can move it out into a separate file:
App_Code folder – which means its going to be compiled as part of the build process
image
@helper Truncate(string input, int length){
    if (input.Length <= length) {
        @input
    }
    else {
        @input.Substring(0, length)<text>...(razor)</text>
    }
}
<h2>@CustomHelpers.Truncate(ViewBag.Message,8)</h2>
Notice we don’t need to cast as a string.  John prefers slightly the declarative way as can do inline on page, then move out.. and can leverage razor
| | # 
# Monday, 05 July 2010
( ASP.NET MVC | Moq )

While using Moq to test an MVC app, and Scott Hanselman’s NerdDinner app, I kept getting these strange errors.

Problem was permissions on:

C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys

In Windows XP Pro, you need to disable simple file sharing.. from http://www.windowsbbs.com/windows-xp/52502-cannot-change-permissions-folder.html

image

Then I set perms to be full control to everyone:

image

More granular perms are in here: http://groups.google.co.uk/group/RhinoMocks/browse_thread/thread/26df68ff01567509/5ddebf407228edc4

Now this code works:

image

On Win7: C:\Users\All Users\Microsoft\Crypto\RSA\MachineKeys

Takes some messing around with granting ownership of the directory, then setting full control to everyone.

| | # 
# Thursday, 01 July 2010

Useful if you want the ASPNETDB to be in your local SQL Server instance rather than a flat file (which can be troublesome).

image

Use trick of connection via server explorer, then F4 properties, then can copy and paste connection string into web.config.

image

| | # 
# Tuesday, 29 June 2010

see about half way down this article for the first working MVC1 app connecting to the db.

http://wag.codeplex.com/

Using the EntLib5

image

Music Store App (Mar 23rd)

image

Hello World sample bits of code from MS:

image

 

Transferring data up to SQL Azure.. using Script Manager in SQL Man Studio 2008..

http://www.msteched.com/2010/NorthAmerica/COS311

 

Doing a Simple MVC Application and Publishing up to the Cloud (no DB)

This is a simple new project, Cloud Service, ASP.NET MVC2 Web Role

Right click on the VoucherMVC project, then publish.  Upload via the Web Interface.

image

NerdDinner

http://www.marcmywords.org/post/NerdDinner-hosted-on-Windows-Azure-and-SQL-Azure.aspx

Failed to generate a user instance due to a failure in starting the process… DB Error:  Solved by deleting a directory on my local machine (Win 7).

http://www.aspdotnetfaq.com/Faq/fix-error-Failed-to-generate-a-user-instance-of-SQL-Server-due-to-a-failure-in-starting-the-process-for-the-user-instance.aspx

 

Populating the Database

http://azurefeeds.com/post/923/Migrating_an_Existing_ASP.NET_App_to_run_on_Windows_Azure.aspx

Showing how to export a SQL script into SQL Azure format:

image

Ok, have got nerddinner database up there. 

ASP.NET Membership Provider..

http://blogs.msdn.com/b/jnak/archive/2009/11/24/asp-net-provider-scripts-for-sql-azure.aspx

http://www.marcmywords.org/post/NerdDinner-hosted-on-Windows-Azure-and-SQL-Azure.aspx

Details how to get the asp.net membership provider scripts working, using modified scripts.

http://support.microsoft.com/kb/2006191/en-gb

 

Issue with NerdDinner MVC2

Came across realm issue with regard to OpenID code, so reverted back to MVC1 code.

NerdDinner MVC1 Migrate to Azure – This Worked

Get it working normally in MVC (with 2 databases running SQLExpress in AppData folder)

Getting the Phone# does not match country error in nerddinner.

hacked the Helper/PhoneValidator.cs to always return true.

image

Deleted the unit test project for simplicity

Added a CloudService project into the solution

Right clicked on Role in CloudService, and added in the existing NerdDinner project

Added back in ConnectionStrings.config into the NerdDinner project

image

Coppied the database to SQL Azure using Management Studio 2008R2

Coppied Membership Provider to SQL Azure using special sql scripts

Added in ConnectionStrings.config into the project, and put in SQL Azure string.

Uploaded to Azure..

**problem goes between stopping and initializing… after 20mins?

Try recreating Service in Asia, and DB is in Asia too.

Try uploading again.. and putting one in staging too ( a simple MVC no database, includes test project, worked before).  9:50pm started.

image

App does work from local using SQL Azure as storage..

image

After sleeping on it, the problem was that copy local wasn’t set to true on the System.Web.Mvc reference.

image

| | # 
# Wednesday, 23 June 2010

While trying to figure out what is meant by the 3rd new section in a view in MVC

<%: Html.ActionLink("Edit", "Edit", new { id=item.DinnerID }) %>

So it is really creating an object with a single property id, which is an int, equal to that of the item, which is a Dinner.

image

“Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to first explicitly define a type”

class Program
{
static void Main(string[] args)
{
// Anonymous types provide a convenient way to encapsulate a set of read-only properties
// into a single object without having to first explicitly define a type
var person = new { Name = "Terry", Age = 21 };
Console.WriteLine("name is " + person.Name);
Console.WriteLine("age is " + person.Age.ToString());

// Anonymous types just get rid of Person1 really.
Person1 person1 = new Person1 { Name = "Bill", Age = 55 };
Console.WriteLine("name is " + person1.Name);
Console.WriteLine("age is " + person1.Age.ToString());
}
}

class Person1
{
public string Name { get; set; }
public int Age { get; set; }
}

Many thanks to the question here for clarifying:
 
| | # 
# Thursday, 27 May 2010

DevDays – MVC – Scott Hanselman video:

WFT1_2MB_ch9.wmv 1.4GB

Looking at the callstack in debug to see how things are called.

image

IHttpHandler – the ‘simple’ building block of ASP.NET.

Example in c:\code\mvc2\hanselman

image

http://localhost:1476/Home/poop/2

Controller get invoked

Action invoker calls the method

Model Binding – took the other piece of the route data (ie 2) and coerced it into…

didn’t call HttpRequest or anything..

 

Passing a DateTime

image

image

Phil Haack Route Debugger

http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx

 

image

prop tab tab to auto gen the properties. then tab tab, then enter enter!

Create A Controller

Ctrl M, Ctrl C

Convention is HomeController

var p = new person

then ctrl period to import the namespace.

Create A View

Convention is in Views directory, create a new Person directory.

Index method links to Index view

Details method links to details view.

image

image

Ctrl M Ctrl V to create a view, when you are in the appropriate Controller class (eg Index)

Created a strongly typed view.. this Viewpage is of type Person

Model in the viewpage will always be of type T ie Person.

Could use Repository Pattern for the DB

Going live with ASP.NET4 – many hosting providers need you to upgrade to another machine.

image

Going Live on Azure

Created a new MVC2 Web Role project

Upload to test that MVC2 is working somewhat

ViewModel - MVCMusicStore

VS2010 Control comma – navigate to

http://mvcmusicstore.codeplex.com/

Uses Entity Framework.

Uses <%: HTml.DisplayForModel

AutoMapper

FirstName, LastName.. map to FirstName and Surname

image

ViewData

is another way to pass data.

image

ViewEngines

This is the WebForms view engine.

Routing

 

NerdDinner – MVC2 in beta (now it is live 27th May)

there are unit test in here.

image

just asserting not null.

Seperation of Concerns – in controller we can’t have Response.Write.. as it would break in this test.  Would work at runtime.

| | # 
# Monday, 22 February 2010

This is useful to get checking on the aspx page at compile time. 

Right click on the project, and select unload.

Edit the .csproj file

image

Set MvcBuildViews to true

Save, reload, compile.

| | # 

The Hands on MVC set of videos:  www.learnvisualstudio.net

Routing

In global.asax

 routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Home", action = "Index", id = ""} // Parameter defaults
);

This means eg http://localhost:3203/Home/About
will come to the controller called HomeController and run the method called About
 
public ActionResult About()
{
return View();
}

which in this case will call the view with the same name called About.aspx

What about http://localhost:3203/ which is the same as /Home and /Home/Index

In this case the defaults are being used eg Home, Index , null… as shown above in //Parameter defaults.

It even passes a message from the Home controller, Index method.

ViewData["Message"] = "Welcome to ASP.NET MVC!";
 
Hardcode /Home to mean something
// for hardcoded /home goto home/member
routes.MapRoute(
"MemberHome",
"home",
new {controller = "Home", action = "Member"}
);

Building UI Form

get is putting in query string

post is putting in the http request body

utility methods for not directly specifying URL


<%Html.BeginForm(); %>






<% Html.EndForm(); %>

Useful to see the Request coming back from /home/member into the HomeController, Member method.

image

asdf

image

Yuk!

Post redirect get pattern.

Basically stops the above resend message by getting the browser to do a redirect after the post page, to a nice get page.

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Member(string status) // this will match up the name status in the forms collection
{
//return View();
return RedirectToAction("Member");
}

The Model using LinqToSQL

Added a simple table with a FK to the aspnet_users UserId column.

 

image


The UserId FK is a guid.

The Timestamp has a default value of GETUTCDATE() so that the db writes in the timestamp.

LinqToSQL has:

readonly – shouldn’t allow app to change it

auto Generated Value = true   - hmm to do with:

Auto_Sync – so it will auto get the timestamp property back into the model whenever it does an insert.

 

Can see the class generated that represents our StatusUpdate table:

image

The View

In the controller:

List updates = db.GetUserUpdates(User.Identity.Name);
return View(updates);

and in the view:

System.Web.Mvc.ViewPage>

we now get a strongly typed object

 

View Models

Have simply created another class called MemberViewModel in Models:

public class MemberViewModel
{
public List Updates { get; set; }
}
 
so can pass in more complex stuff than just a list into my view (can’t pass in multiple lists)
 
So the view now has:
 
System.Web.Mvc.ViewPage

and we can access data like:
 
foreach (var update in Model.Updates)

 

Lazy Loading and Eager Loading.

However we’ve hit an interesting issue:

image

this is because of in the view we’ve called:

Html.Encode(update.User.UserName)

And in the actual query, it returns only the StatusUpdate object and not the User object (even though it does a join).

var updates = from update in this.StatusUpdates
where update.User.UserName == userName
orderby update.Timestamp descending
select update;
 
in the controller after query is ran and the result put into the ViewModel, then passed to the View… the datacontext is destroyed.
 
using (var db = new TwixDataContext())
{
ViewData["Stuff"] = "Blah this is a generic object with no intellisense";

MemberViewModel model = new MemberViewModel
{
Updates = db.GetUserUpdates(User.Identity.Name)
};
//List updates = db.GetUserUpdates(User.Identity.Name);
return View(model);
}


So when the view tries to call the User.UserName.. LinqToSQL tries to go and get this data, as it hasn’t been needed yet.  This is lazy loading.

We want LinqToSQL to load the User object at the same time as loading the StatusUpdates.. this is Eager Loading.

CSS

Making things look good:

#timeline { list-style: none; padding: 0;}
#timeline li {border-top:dashed 1px #888; padding: 5px 0; }
#timeline li:hover { background-color: #eee; }
#timeline li div.message { font-size: 10pt; }
#timeline li div.message span { font-weight: bold; }
#timeline li div.time { font-size: 8pt; font-style: italic }

for:

    "timeline">
    <%foreach (var update in Model.Updates) {%>


  • class="message">
    <%= Html.Encode(update.User.UserName) %>:
    <%=Html.Encode(update.Message) %>

    class="time">
    <%=update.Timestamp.ToLocalTime().ToString() %>


  • <%} %>
Creating a Home/Profile

coppied the get from index, however instead of passing in the current logged in user to GetUserUpdates, am passing in the string ie it will be localhost/nameofperson or localhost/home/profile/nameofperson

Also created a new viewmodel for profile that has username in it (as we’ll need this).  Strongly typed as well.

public class ProfileViewModel
{
public string UserName { get; set; }
public List Updates { get; set; }
}

Partial View (#7)

create a viewmodel just for the timeline ie this partial view.

changing MemberViewModel and ProfileViewModel to have a TimeliveViewModel (abstracting it away to get rid of duplication)

public class MemberViewModel
{
public TimelineViewModel TimelineModel { get; set; }
}

public class TimelineViewModel
{
public List Updates { get; set; }

So we reference it in the controller like this:

ProfileViewModel model = new ProfileViewModel
{
UserName = userName,
TimelineModel = new TimelineViewModel{
Updates = db.GetUserUpdates(userName)
}
};
and then in the view:
<%foreach (var update in Model.TimelineModel.Updates) {%>

Hyperlinks, Anonymous Type - create new view as Timeline.ascx

<%Html.RenderPartial("Timeline", Model.TimelineModel); %>
 
<%Html.ActionLink(update.User.UserName, "profile", new {userName = update.User.UserName}) %>

First property is the text to be displayed, second is the action to be called when they click this link (method on this controller),

We’re not specifying the controller here, so it is going to user the current (home) controller.

The third is a generic object which represents the extra route values that we want.. as the method takes a parameter called userName, we need to pass it. We use an anonymous type

 

image

The crowd goes wild :-)

Seeing Other Peoples Tweets

A common technique when we need a Many to Many relationship. 

each user can follow many other users

each user can be followed by many other users

image

The primary key is both on the FollowerMappings table.

Then in the Mappings:

image

We have renamed the child and parent properties for clarity.

The first FK relationship is the FollowerId being held constant.  So the Child Property is the Followee (all the people the user is following)

The second FK relationship is the FoloweeId being held contact.  So the Child Property is the Follower (all people who are following the user).

**TODO refactor and come up with better names.

Adding Methods to The Model DataContext

GetAllUpdates – gets all status update records including those psoted by user that this user is following

IsFollowing – checks if a specific user name is following another user name… so we know whether to display a button

DeleteFollowerMapping

Adding Methods to the HomeController

Changed the get method on Home/Profile to GetUserUpdates.. and to do logic for displaying the Follow/Stop Following button.

Added a post method for Follow (which is called from Profile as a form post), and redirects back to Profile.

 

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Follow(string userName)
{
if (!string.IsNullOrEmpty(userName) && !userName.Equals(User.Identity.Name, StringComparison.OrdinalIgnoreCase))
{
using (var db = new TwixDataContext())
{
if (!db.IsFollowing(User.Identity.Name, userName)) // double check they are not already being followed
{
var followerMapping = new FollowerMapping
{
FollowerId = db.GetUserIdForUserName(User.Identity.Name),
FolloweeId = db.GetUserIdForUserName(userName)
};

db.FollowerMappings.InsertOnSubmit(followerMapping);
db.SubmitChanges();
}
}
}
return RedirectToAction("Profile", new {userName = userName});
}

Added a post method for StopFollowing.. same as above.

Adding Properties to the ProfileViewModel

public class ProfileViewModel
{
public string FollowText { get; set; }
public string FollowAction { get; set; }
public bool IsSelf { get; set; }
public string UserName { get; set; }
public TimelineViewModel TimelineModel { get; set; }
}
So when we pass this object to the view, we’ve got lots of strongly typed goodness.

Using in the View

using (Html.BeginForm(Model.FollowAction, "home")) {
%>
<%=Html.Hidden("userName", Model.UserName) %>

<%
}

where the brace ends, is just the same as doing an Html.EndForm.

 

Best Practise

Use a form post instead of a link if doing database stuff to prevent hacking.

Summary so Far

Why do we have so much business logic in the controller?

DSCN1403

next video is #9

why is this line sometimes giving Http Exception in home controller.

var isSelf = userName.Equals(User.Identity.Name, StringComparison.OrdinalIgnoreCase);

#9 – is jQuery.. thats all folks or more stuff.

#10 – is account settings.. name, email, timezone.. form field validation… combo box (dropdown)… nice fade out jquery front end.

#11 – is upload photo

#12 – is search.. ?q=learnvisualstudio… not a post… stuff in his source code that isn’t in video. icon/link delete a post.

| | # 
# Friday, 19 February 2010

Pairing with Michael, we did our first spike from here:

http://ericdotnet.wordpress.com/2009/04/09/jquery-search-box-and-aspnet-mvc/

worked fine locally, but then going live getting some issues.  Looked like it was mateerit.co.nz/search

<script src=" <%=Url.Content("~/Scripts/jquery-1.3.2.js") %>" type="text/javascript"></script>

The above seemed to work, however the javascript seemed harder:

<script type="text/javascript">

$(document).ready(function() {
$("#searchTerm").autocomplete("/Home/getAjaxResult/");
});

</script>

so I cheated and went onto a subdomain:  jsearch.mateerit.co.nz

All works now with firebug too.

image

| | # 
# Tuesday, 16 February 2010

http://www.mikesdotnetting.com/Article/128/Get-The-Drop-On-ASP.NET-MVC-DropDownLists

1) SelectListItem – Value and Text property assigned

var db = new northwindDataContext();
IEnumerable<SelectListItem> items = db.Categories.Select(c => new SelectListItem {Value = c.CategoryID.ToString(), Text = c.CategoryName});
ViewData["CategoryID"] = items;
 
in the view:
<%= Html.DropDownList("CategoryID") %>

which is the pretty much the same as:
 
<%= Html.DropDownList("CategoryID", (IEnumerable<SelectListItem>)ViewData["Categories"]) %>

2) SelectList is tidier, and gives a couple of overloads including selected (in the case below number 3):
 
var query = db.Categories.Select(c => new {c.CategoryID , c.CategoryName});
ViewData["Categories"] = new SelectList(query.AsEnumerable(), "CategoryID", "CategoryName",3);

image
 

PostBack

On the product view:

<% using (Html.BeginForm(null, null, FormMethod.Post, new { id = "TheForm" })) {%> 
<%=Html.DropDownList("CategoryID", (SelectList)ViewData["Categories"], new { onchange="this.form.submit();"})%>
<%}%>

and the product controller:

public ActionResult Index(int? categoryid)
{
var db = new northwindDataContext();

var query = db.Categories.Select(c => new {c.CategoryID, c.CategoryName});
ViewData["Categories"] = new SelectList(query.AsEnumerable(), "CategoryID", "CategoryName");

List<Product> products;
if (categoryid == null)
products = db.Products.ToList();
else
products = (from p in db.Products
where p.CategoryID == categoryid
select p).ToList();
return View(products);
}

which gives:
 
image 
Used LinqToSQL.
ASP.NET MVC version 1
 

Run Implementation

Found I had to sort a generic list
 
The crowd goes wild:
image
| | # 
# Monday, 15 February 2010

Both my asp.net web hosters advertised they are hosting on Server 2008, which meant IIS7.  This makes things much easier when publishing an MVC site (to do with routing apparently).  As I’d hosted my sites for years with these providers, they were still on Win2003 (IIS6) boxes.  I just had to ask for an upgrade and it was done.

Upload to IIS7 and it just works!

The first step was to see if routing worked on the default website.. it did!

The next step – to publish up the NerdDinner app I’ve been going through on Rob Conery, and get the database connected live.

image

The crowd goes wild  - this is live and connecting to a database :-)

Changing Namespace / Solution Name / Project Names

I had lots of namespace errors.. forgot to change default assembly namespace, which meant linq to sql was in the wrong space.  However it is possible to change everything very quickly – solution, project names, directly.  One gotcha was remembering to delete everything on the live server so there weren’t 2 dll’s with the same object names inside..

Changing Default Page to Activity / upload live trick

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Activity", action = "Index", id = "" } // Parameter defaults
);

Change controller = “Home” to controller = “Acitivity”

I also implemented the copyifnewer.bat trick for easily going from dev to live which is here: http://www.programgood.net/2010/01/28/WebConfigAutomatingDevAndLive.aspx

Run application working live with Create, Read, Update and Delete working.  Also validation, which comes for free in the standard templates.

image

DropDownList and Postbacks – covered in another post on this site.

http://www.mikesdotnetting.com/Article/128/Get-The-Drop-On-ASP.NET-MVC-DropDownLists

Summary Page

I created another link in the master page for menu item:

www.mateerit.co.nz/run

image

For the summary page I’m considering a ViewModel approach.

Lets see if a simple new Summary controller will suffice

Got to a stage.. was going to upload to github, but had db connection strings in there which didn’t want in the history.. so looked at rebase in git.. want to make sure before I play too much :-)

 

Creating a SQL View then Displaying it

Michael came up with an elegant solution which I’m trying.. so creating a SQL View:

SELECT     personid,    
DATEPART(week, date) AS Week,
DATEPART(year, date) AS Year,
SUM(kilometres) AS kilometres,
SUM(hours) AS hours
FROM dbo.Activity
GROUP BY personid, DATEPART(week, date), DATEPART(year, date)

which gives a good summary output:

image

The aim is to be able to see the summary of each week like this (this is the old webforms version)

image

linq to sql generated classes off the view.

Michael did it like this:

image

I’m on this:

image

Passing Complex Data – Lists within Lists

As each person has data associated to them, a list within a list is good.

image

public class WeekSummary
{
public int Personid;
public string Personname;
public List<WeekSummaryData> Persondata;
}

public class WeekSummaryData
{
public double? Hours;
public double? Kilometers;
public int? Week;
public int? Year;
}

Then in the repository:

public IQueryable<WeekSummary> GetWeeklySummary()
{
var weekSummaries = from p in db.Persons
orderby p.personname
let data = GetWeeklySummaryData(p.personid)
select new WeekSummary {Personid = p.personid,
Personname = p.personname,
Persondata = new List<WeekSummaryData>(data)};
return weekSummaries;
}

IQueryable<WeekSummaryData> GetWeeklySummaryData(int personid)
{
var summary = from w in db.weekly_summaries
where w.personid == personid
orderby w.Year , w.Week
select new WeekSummaryData {Hours = w.hours,
Kilometers = w.kilometres,
Week = w.Week,
Year = w.Year};
return summary;
}

** understand this linq

Then in the controller:

public ActionResult Index()
{
var summaries = _repository.GetWeeklySummary();
return View(summaries);
}

and the view:

** understand this rendering

<% foreach (WeekSummary weekSummary in Model) {
%>
<table>
<tr>
<th></th>
<% foreach (WeekSummaryData weekSummaryData in weekSummary.Persondata) { %>
<th><%=Html.Encode(weekSummaryData.Week) + "/" + Html.Encode(weekSummaryData.Year) %></th>
<%}%>
</tr>
<tr>
<td>
<%=Html.Encode(weekSummary.Personname) %>
</td>
<% foreach (WeekSummaryData week in weekSummary.Persondata) { %>
<td><%=Html.Encode(week.Hours) + "hrs" %><br /><%=Html.Encode(week.Kilometers) + "kms" %></td>
<%}%>
</tr>
</table>
<% } %>

 

refactor code with an interface for testing

unit test do

automock

jquery

tooling to help make form crud websites faster…

reproting tooling

mvc2

| | # 
# Thursday, 11 February 2010

No error.  Just closes when using ASP.NET MVC

http://stackoverflow.com/questions/1361291/resharper-r-4-5-and-mvc-1-0-solutions-cause-visual-studio-2008-sp1-to-crash

then onto:

http://stackoverflow.com/questions/500696/why-does-visual-studio-crash-opening-aspx-with-mvc-rc1

Have tried the one above, which seems to work so far.

[Edit] it didn’t.. so now I’m trying this:

https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=16827&wa=wsignin1.0

Something still weird as locking up when loading assemblies (looks like resharper)  am trying resharper5 beta2 to see if that helps (haven’t got correct license).  I can get around lockup by deleting dlls from bin and obj.

| | #