Best asp.net-mvc questions in October 2011

Commonly-accepted approach in MVC for form within jQuery dialog

11 votes

There seem to be several ways to integrate jQuery dialogs with ASP.NET MVC. Has a specific approach emerged as the commonly-accepted best-practice way to do so?

As an example: I have a list page where clicking "edit" for any of the listed items opens a form in a jQuery dialog, populated with the item's details. User edits details and clicks "save". If the save succeeds on the server-side, the dialog is closed and the list is re-built with fresh data. If the save fails on the server-side, the dialog remains open and displays the error message(s) to the user.

  1. No-JSON approach: each "edit" link is an HREF to an "edit" controller action. That controller action builds a view that is identical to the "list" view, plus it includes a partial action to build the edit form, populate it, and define the javascript to pop it open as a jquery dialog. The "save" is a form-post; if it succeeds, it returns a redirect action back to the list page. If it fails, it rebuilds the entire page (including the form that pops up in a dialog) displaying the error messages as well.
  2. All-JSON approach: the list page renders an empty edit form (hidden), ready to be popped open into a dialog. The "edit" link calls local javascript which does an ajax request to get the full object (I define a controller which returns the full object as a JsonResult). On success, it fills the edit form with the object's data and opens the dialog. The "save" link calls local javascript which bundles the form data into a json object, and calls a post operation with that json object as payload (I define a controller which expects that object, attempts the save, and returns a JsonResult indicating success/failure+errorMessages). Success callback from the ajax request evaluates the returned object, and either shows the error messages in the still-open jquery dialog, or closes the dialog and reloads the "list" page to get fresh data in the list.
  3. [Edit] Ajax-HTML approach: just saw this SO discussion which describes another approach. The "edit" calls local javascript which does an ajax post to get the FULL HTML of the dialog (I would write a controller which returns a partial view: the fully-populated form). It renders the returned HTML into a jquery dialog, and also "re-wires" the form submission to do an ajax-post of the form's contents (I would write an httpPost controller, same as in #2 above). The success callback evaluates the response and populates error messages or closes the dialog.
  4. Some other cool approach I haven't thought of?

Option 1 seems to be more in keeping with "pure" ASP.NET MVC. However, it seems to feature big HTTP payloads (since we're shipping the full page back to the browser on every request), and slower server-side performance (since we're re-building the list on every request).

Option 2 seems to be more consistent with more modern Ajax-based web applications (smaller HTTP payloads, more granular operations). However, it seems like many of the controllers will be JSON controllers, and I'll be writing a lot of client-side code to marshal data from JSON objects to/from form fields, display error messages, etc. It also seems like I'd be missing out on a lot of cool MVC features like EditorFor() and ValidationMessageFor(). It just "feels" like I'm working around the MVC system instead of with it.

[Edit: added option 3] Option 3 seems to be a bit of a hybrid between 1 and 2. I use the "pure" MVC approach to build and populate the form, and return a fully-formed HTML FORM tag. Returning HTML to an ajax request feels weird since it's so verbose, but I can get over it. The post operation is nice, compact JSON which "feels" better over ajax. However, it's unfortunate that the payload object is a FormCollection rather than a real viewmodel object. It seems like I can make use of some of the MVC conveniences (EditorFor()) but not others (ValidationMessageFor()).

I'm looking for the "right" way to do this, not just the fastest way to hack it together. Yeah, yeah, I know there's no universally "right" way. But I'm sure there's some notably wrong ways to do it, and I want to avoid them.

I'm pretty experienced in ASP.NET/C#, but I'm pretty new to MVC. Thanks in advance for your help!

[Edit] - outstanding responses - I wish I could award multiple answers/bounties, as I found several responses extremely useful. But since I can't, I'm marking the top-voted response as the answer. Thanks again to all respondents!

My team and I have a lot of experience writing AJAX enabled MVC apps, and we have used all 3 approaches.

However, my favorite is definitely the AJAX-HTML approach -- Use a PartialView to render the contents of the dialog, which could include server-side validation messages and any other logic.

The biggest benefit of this approach is the separation of concerns - your Views are always responsible for rendering your HTML, and your JavaScript doesn't have to contain any text, markup, or "templates" needed to render the JSON.

Another big advantage is that all the great MVC features are available for rendering the HTML: strongly-typed views, HtmlHelper, DisplayFor and EditorFor templates, DataAnnotations, etc. This makes it easier to be consistent and lends well to refactoring.

Just remember, there's no requirement to stick to a single approach. When your AJAX call only needs something simple, such as a status update like "Success", it's fine to just use a string or JSON to convey those messages. Use PartialViews when HTML is needed, and use simpler methods when communication is needed.

Dependency Injection what´s the big improvement?

10 votes

Currently I'm trying to understand dependency injection better and I'm using asp.net MVC to work with it. You might see some other related questions from me ;)

Alright, I'll start with an example controller (of an example Contacts Manager asp.net MVC application)

public class ContactsController{

  ContactsManagerDb _db;

  public ContactsController(){

    _db = ContactsManagerDb();

  } 

  //...Actions here
}

Allright, awesome that's working. My actions can all use the database for CRUD actions. Now I've decided I wanted to add unit testing, and I've added another contructor to mock a database

public class ContactsController{

  IContactsManagerDb _db;

  public ContactsController(){

    _db = ContactsManagerDb();

  }

  public ContactsController(IContactsManagerDb db){
    _db = db;
  }

  //...Actions here
}

Awesome, that's working to, in my unit tests I can create my own implementation of the IContactsManagerDb and unit test my controller.

Now, people usually make the following decision (and here is my actual question), get rid of the empty controller, and use dependency injection to define what implementation to use.

So using StructureMap I've added the following injection rule:

x.For<IContactsManagerDb>().Use<ContactsManagerDb>();

And ofcourse in my Testing Project I'm using a different IContactsManagerDb implementation.

x.For<IContactsManagerDb>().Use<MyTestingContactsManagerDb>();

But my question is, **What problem have I solved or what have I simplified by using dependency injection in this specific case"

I fail to see any practical use of it now, I understand the HOW but not the WHY? What's the use of this? Can anyone add to this project perhaps, make an example how this is more practical and useful?

The first example is not unit testable, so it is not good as it is creating a strong coupling between the different layers of your application and makes them less reusable. The second example is called poor man dependency injection. It's also discussed here.

What is wrong with poor man dependency injection is that the code is not autodocumenting. It doesn't state its intent to the consumer. A consumer sees this code and he could easily call the default constructor without passing any argument, whereas if there was no default constructor it would have immediately been clear that this class absolutely requires some contract to be passed to its constructor in order to function normally. And it is really not to the class to decide which specific implementation to choose. It is up to the consumer of this class.

How to measure memory usage for a Live ASP.NET MVC web application?

8 votes

So right off the bat, not sure if this question is better suited for another StackExchange site.

I've got an ASP.NET MVC 3 web application running on Windows Server 2008 and IIS 7.5

Site runs fine initially, but i can see the memory usage gradually growing. After about 12 hours it's nearly out of memory and the site chokes.

I'm using a lot of caching, so i'm thinking this combined with some possibly memory leaks is the cause of the issue.

So my question - what's the best way (tools, for example) to monitor memory usage on a web server running ASP.NET MVC?

In the past i've used good old' perfmon and put the IIS counters on to measure these things.

It this still the best way, and if so, can someone recommend a good perfmon counter template for my scenario?

Perfmon's counters are still a good technique (and free!). PAL (Performance Analysis of Logs), a free tool, has an ASP.NET perfmon counter template for general health (in addition to generating reports of counter log files based on thresholds).

Check out:

.NET Debugging Demos Lab 7: Memory Leak

.NET Memory Leak Case Study: The Event Handlers That Made The Memory Baloon

Tracking down managed memory leaks (how to find a GC leak)

Determine if your .NET Application has a Memory Leak

Commercial tools like MemProfiler, RedGate's memory profiling tool and JetBrains Profiler are all very good (and all have free trials).

What is the most efficient way to do comparisons involving many-many relationships with LINQ in EF 4.1?

7 votes

In my database I have the following tables:

  • Person
  • Post
  • InterestTag

Many-Many relationships exist between Person-InterestTag and Post-InterestTag

I need to perform a linq query in EF 4.1 to pull back any post that contains at least one interest tag that matches at least one interest tag related to the given user.

Example

A person has the following interests:

  • Cars
  • Sports
  • Fitness

I need to return any Post that is related to either cars, sports, or fitness.

What is the most efficient way to write this query in terms of performance?

Edit

Running into an error based on the answer given below...

This compiles fine but throws an error at runtime:

var matchingPosts = posts.Where(post => post.Topics.Any(postTopic =>   person.Interests.Contains(postTopic)));

The error is:

Unable to create a constant value of type 'System.Collections.Generic.ICollection`1'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

Any ideas how to fix this?

EDIT 2

So my classes are structured as such:

public class Person
{
    public int PersonID {get; set;}
    public string FirstName {get; set;}
    public string LastName {get; set;}
    //other properties of types string, int, DateTime, etc.

    public ICollection<InterestTag> InterestTags {get; set;}      
}


public class Post
{
    public int PostID {get; set;}
    public string Title{get; set;}
    public string Content {get; set;}
    //other properties of types string, int, DateTime, etc.

    public ICollection<InterestTag> InterestTags {get; set;}


}

public class InterestTag
{
    public int InterestTagID { get; set; }
    public string InterestDescription { get; set; }
    public bool Active { get; set; }

    public ICollection<Person> Persons { get; set; }
    public ICollection<Post> Posts { get; set; }
}

In my Context class I am overriding OnModelCreating to define my DB table names

modelBuilder.Entity<Person>().HasMany(u => u.InterestTags).WithMany(t => t.Persons)
    .Map(m =>
    {
        m.MapLeftKey("PersonID");
        m.MapRightKey("InterestTagID");
        m.ToTable("PersonInterestTags");
    });

modelBuilder.Entity<Post>().HasMany(u => u.InterestTags).WithMany(t => t.Posts)
    .Map(m =>
    {
        m.MapLeftKey("PostID");
        m.MapRightKey("InterestTagID");
        m.ToTable("PostInterestTags");
    });

In my query method I am bring back an IQueryable of Post and applying some filters, including the clause in which I am trying to accomplish in this question.

 var person = personRepository.Get(x => x.PersonID = 5);
 var posts = postRepository.GetQueryable();

 //I have tried this and get the error above
 posts= posts.Where(x => x.InterestTags.Any(tag => person.InterestTags.Contains(tag)));

If you start with just a given personId (or userId) you can do this query in one roundtrip like so:

var posts = context.Posts
    .Intersect(context.People
        .Where(p => p.Id == givenPersonId)
        .SelectMany(p => p.InterestTags.SelectMany(t => t.Posts)))
    .ToList();

This translates into an INTERSECT statement in SQL.

You can also do this in two roundtrips:

var interestTagsOfPerson = context.People.Where(p => p.Id == givenPersonId)
    .Select(p => p.InterestTags.Select(t => t.Id))
    .SingleOrDefault();
// Result is an IEnumerable<int> which contains the Id of the tags of this person

var posts = context.Posts
    .Where(p => p.InterestTags.Any(t => interestTagsOfPerson.Contains(t.Id)))
    .ToList();
// Contains translates into an IN clause in SQL

Using a list of primitive types in the second query (interestTagsOfPerson is a collection of int) also fixes the error you mentioned in your Edit in the question. For Contains you cannot use object references in LINQ to Entities because EF doesn't know how to translate that into SQL.

I have no clue which of the two approaches is faster (SQL experts might have a better idea) but would probably start to test the first option. (I've tested a little bit and it seemed to return the correct results, but it's the first time that I have used Intersect.)

Edit

To give an idea of the generated SQL (captured from SQL Profiler):

The first query (with Intersect) creates this SQL query:

SELECT 
[Intersect1].[Id] AS [C1], 
[Intersect1].[Name] AS [C2], 
FROM  (SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Name] AS [Name], 
    FROM [dbo].[Posts] AS [Extent1]
INTERSECT
    SELECT 
    [Join1].[Id] AS [Id], 
    [Join1].[Name] AS [Name], 
    FROM  [dbo].[PersonInterestTags] AS [Extent2]
        INNER JOIN (SELECT [Extent3].[TagId] AS [TagId],
                           [Extent4].[Id] AS [Id],
                           [Extent4].[Name] AS [Name]
                    FROM  [dbo].[PostInterestTags] AS [Extent3]
                    INNER JOIN [dbo].[Posts] AS [Extent4]
                        ON [Extent3].[PostId] = [Extent4].[Id] ) AS [Join1]
            ON [Extent2].[TagId] = [Join1].[TagId]
    WHERE 1 = [Extent2].[PersonId]) AS [Intersect1]

The second option:

Query1 (for the list of the person's tag Ids):

SELECT 
[Project1].[Id] AS [Id], 
[Project1].[C1] AS [C1], 
[Project1].[TagId] AS [TagId]
FROM ( SELECT 
    [Limit1].[Id] AS [Id], 
    [Extent2].[TagId] AS [TagId], 
    CASE WHEN ([Extent2].[PersonId] IS NULL)
                 THEN CAST(NULL AS int)
                 ELSE 1
             END AS [C1]
    FROM   (SELECT TOP (2) [Extent1].[Id] AS [Id]
        FROM [dbo].[People] AS [Extent1]
        WHERE 1 = [Extent1].[Id] ) AS [Limit1]
    LEFT OUTER JOIN [dbo].[PersonInterestTags] AS [Extent2]
            ON [Limit1].[Id] = [Extent2].[PersonId]
)  AS [Project1]
ORDER BY [Project1].[Id] ASC, [Project1].[C1] ASC

Query 2 for the final posts:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name], 
FROM [dbo].[Posts] AS [Extent1]
WHERE  EXISTS (SELECT 
            1 AS [C1]
        FROM [dbo].[PostInterestTags] AS [Extent2]
WHERE ([Extent1].[Id] = [Extent2].[PostId]) AND ([Extent2].[TagId] IN (1,2,3))
)

In this example the query 1 returned (1,2,3), hence the (1,2,3) in the IN clause in query 2.

How are you populating/validating your ViewModels?

7 votes

I'm curious of all of the various ways people are building their ViewModels and why they choose that method.

I can think of several ways here:

-1. Injected repository - the controller loads the model and maps to the ViewModel. Here the ViewModel constructor could take various collections to interally set for ex. in a select list such as:


public CustomerController(ISomeRepository repository)
{
   _repository = repository;
}

public ActionResult Create()
{
  CustomerCreateViewModel model = new CustomerCreateViewModel(_repository.GetShipTypes, 
                                                                _repository.GetStates);
..
..
}

-2. ViewModelBuilder - Either injected or instantiated in the controller with an instance of the injected repository. Called via something like

>var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);

or,

var orderViewModel = orderViewModelBuilder.WithStates().Build(orderId);

-3. Directly in controller (no code required - its messy)

-4. Some other service (injected or not) that returns domain model which the controller then maps or a ViewModel (anyone doing this to return a view model that isn't specifically named/noted as a ViewModel builder class?)


public JobCreateViewModel BuildJobCreateViewModel(int parentId)
{
   JobCreateViewModel model = new JobCreateViewModel();
   model.JobStatus = _unitOfWork.JobRepository.GetJobStatuses();
   model.States=_unitOfWork.StateRepository.GetAll();
   return model;
}

Now on the return trip - regarding validating your view models - are you inheriting from a base ViewModel class for standard validations, or copying your validations (ex. data annotation attributes) between all of your ViewModels, or simply relying on server side validation so it can all be validated againt your domain object?

Any others? Anything better? Why?

EDIT Based on a link below, I did find a nice article from Jimmy Bogard on the architecture of ViewModels. While it doesn't address the question above directly, it's a great reference for anyone coming here for ViewModel information. http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/

I inject a service into the controller, not a repository, and then use AutoMapper to convert it into a view model. The benefit of the service layer in this case is that it could aggregate multiple simple operations from one or more repositories into a single operation exposing a domain model. Example:

private readonly ICustomerService _service;
public CustomerController(ICustomerService service)
{
    _service = service;
}

[AutoMap(typeof(Customer), typeof(CustomerViewModel))]
public ActionResult Create(int id)
{
    Customer customer = _service.GetCustomer(id);
    return View(customer);
}

in this example AutoMap is a custom action filter that I can write which executes after the controller action, inspects the returned object and uses defined AutoMapper mappings to map it to the specified destination type. So the view gets the corresponding CustomerViewModel as model type. Would have been equivalent to:

public ActionResult Create(int id)
{
    Customer customer = _service.GetCustomer(id);
    CustomerViewModel vm = Mapper.Map<Customer, CustomerViewModel>(customer);
    return View(vm);
}

it's just that it is too much plumbing and repetitive code that could be centralized.

I would also recommend you watching the putting your controllers on a diet video from Jimmy Bogard.

Custom ValidationAttribute not firing IsValid function call in view model

6 votes

I have created my own custom ValidationAttribute:

public class UrlValidationAttribute : ValidationAttribute
{
    public UrlValidationAttribute() {}

    public override bool IsValid(object value)
    {
        if (value == null)
            return true;

        var text = value as string;
        Uri uri;

        return (!string.IsNullOrWhiteSpace(text) && 
                Uri.TryCreate(text, UriKind.Absolute, out uri));
    }
}

I am using that on one of my models and it works perfectly. However, now I am attempting to use it on a view model:

public class DeviceAttribute
{
    public DeviceAttribute(int id, attributeDefinition, String url)
    {
        ID = id;
        Url = url;
    }

    public int ID { get; set; }

    [UrlValidation]
    public String Url { get; set; }
}

The view model is used in the partial view like this:

@model List<ICMDB.Models.DeviceAttribute>

<table class="editor-table">

@foreach (var attribute in Model)
{
    <tr>

        @Html.HiddenFor(a => attribute.ID)

        <td class="editor-label">
            @Html.LabelFor(a => attribute.Url)
        </td>

        <td class="editor-field">
            @Html.TextBoxFor(a => attribute.Url)            
            @Html.ValidationMessageFor(a => attribute.Url)
        </td>

    </tr>
}

</table>

For some unknown reason, while the constructor for UrlValidationAttribute fires, the IsValid function doesn't fire. Any ideas?

Edit: On further investigation, it seems this is happening because the DeviceAttribute view model is actually the view model for a partial. The full page is passed a different view model that contains the list of DeviceAttribute view models. So when my controller action is called, the full page view model is constructed and its values filled, but no DeviceAttribute view models are constructed, hence why no validation is run.

I would recommend you using editor templates instead of writing foreach loops. I suppose that your main view model looks something like this:

public class MyViewModel
{
    public List<DeviceAttribute> Devices { get; set; }
    ...
}

Now in your main view:

@model MyViewModel
@using (Html.BeginForm())
{
    <table class="editor-table">
        @Html.EditorFor(x => x.Devices)
    </table>
    <input type="submit" value="OK" />
}

and in the corresponding editor template (~/Views/Shared/EditorTemplates/DeviceAttribute.cshtml):

@model DeviceAttribute
<tr>
    @Html.HiddenFor(x => x.ID)

    <td class="editor-label">
        @Html.LabelFor(x => x.Url)
    </td>

    <td class="editor-field">
        @Html.TextBoxFor(x => x.Url)            
        @Html.ValidationMessageFor(x => x.Url)
    </td>
</tr>

And your POST action takes the view model back:

[HttpPost]
public ActionResult Index(MyViewModel model)
{
    ...
}

Now the default model binder will successfully bind all values in the view model and kick validation.

Here's a nice blog post about templates.

Opensource projects to learn asp.net mvc 3

6 votes

I have basic knowledge of Java and some experience with MVC pattern. I have followed asp.net mvc 3 tutorials and video's from The official Microsoft ASP.NET site and now want to move permanently to asp.net mvc 3.

Personally i think one of the best ways doing this is to contribute in an opensource project to learn from. But don't know how to achieve this.

For example how can i register for opensource project ? Does someone know an opensource project where i can leran from ? Specifically asp.net MVC.

Thnx,

I think this topic is more suited for programmers.stack-exchange. Anyhow you usually do not need to register for open source projects. You simply fork your version of the code add features and then send a patch/pull request to the owners. One of the better ways to start contributing to an opensource project is to go over the bug list and see what can you help fixing, this will teach you a lot about the codebase.

To find opensource projects you can scout this places:

Good luck :-)

Security in MVC Views

6 votes

In my MVC application I have a few different roles: Admin, General User, etc., etc.

I know that I can apply security to my Controllers via the Authorize attribute:

[Authorize(Roles="Admin")]
public ActionResult Create()
{
    return View();
}

But I also need to apply some security to the Views to not display certain sections of the View to certain roles:

@if( User.IsInRole("Admin") )
{
    @Html.ActionLink("Create", "Create")
}

Is it better to do it the above way, or handle this sort of security in a ViewModel:

public ActionResult Index()
{
    var model = new IndexViewModel();

    model.CanCreate = User.IsInRole("Admin");

    return View(model);
}

View:
@( Model.CanCreate )
{
    @Html.ActionLink("Create", "Create")
}

Does the second method have any benefits compared to the first or is it just a preference thing?

The second way is more preferred, as your business logic will stay at model level.

In your example, business logic is very simple. However, imagine that requirements have changed and now not only Admins can create content, but also General Users that signed up more than 1 month ago. With business logic in view you'd have to update all your views.

Suggest a weekend learning track for MVC3 for someone familiar ASP.NET web forms development

5 votes

I have a "green field" project I'll be starting monday, and it's an intranet business application that wants to do all the typical stuff like workflow, alerts. The Model is done with EF and has all the core entities that a 50 person company would be expected to have plus a model of business specific accounting procedures - every entity corresponds to a noun in the employees' nomenclature.

I spent a good deal of spare time in the past few months learning sharepoint 2010 and it definately has facilities for everything this project wants to be (think enthusiastic business owner who recently woke up to the possibilities of life beyond excel sheets). I may not have the opportunity to get up on the sharepoint curve quickly enough and this means writing it from scratch.

The main things I need to deal with are: - grid style data forms - active directory based authentication - email integrated alerts and event driven workflow - professional appearance similar to default sharepoint 2010 theme

I know how I'd do it with web forms. It would not be trivial by any means - Providers, .ASCX Controls, Validators, Masterpages, Themes, Skins, tied together with a project specific class library to support cross-cutting issues. I have this architecture in my mind and it's worked for me on other projects - I can predict to myself the success and schedule, which makes my stress level manageable.

That said, I get the distinct imppression from the "blog-o-sphere" that I'd be doing myself a disservice if I didn't at least try to use MVC for this.

I started researching and found the Documentation Resources for ASP.NET MVC 3 and, well, I just don't know where to begin.

I have this weekend to decide if I can do it because Monday I've gotta go in with a game plan.

If, from my description, someone could recommend a tutorial and/or a clean open source example, I'd be very thankful.

I suggest you get this book (e-book version). It contains a real walk through example on the first chapter that you can follow, and then as you move along, the author also tells you why you do certain things the way the are. I'm sure with your experience (as you describe) with webforms, this book should be sufficient for you to make a decision over the weekend.

Just out of curiosity though (in a pragmatic point of view), if you believe you can do this easily using webforms, why the trouble learning MVC over the weekend? Wouldn't you be disservicing yourself then :)?

Advise on setting up seed data using nhibernate during development (not test suite)

5 votes

How should one go about setting up seed data while developing an nhibernate web application? (It's Mvc)

Should I just create a method and have it fire during application load (when it debug mode), and simply comment it out when I don't need it?

or is there a better way?

I suggest looking at something like AutoPoco.

AutoPoco replaces manually written object mothers/test data builders with a fluent interface and an easy way to generate a large amount of readable test data. By default, no manual set-up is required, conventions can then be written against the names/types of property or manual configuration can be used against specific objects.

The primary use cases are

  • Creating single, valid objects for unit tests in a standard manner across all tests
  • Creating large amounts of valid test data for database population

This is not tied directly to NHibernate - you could in theory combine it with any data-layer that can persist POCO's.

I'd avoid adding code to Application_Start though - that sounds like a recipe for accidentally trashing your production database. You'd be better off creating a simple console application that you can run whenever you want to reseed your database.

What is the best place for business logic in ASP.NET MVC when using repositories?

5 votes

When implementing Repository for database in ASP.NET MVC project, is it correct to place business logic into it or may be better to place logic in controller class? Or use additional service and helper classes for manipulating data?

Ultimately there isn't a perfect place for your business logic besides its own layer (as part of the "Model" layer). Often you can get away with a different implementation, but there are trade offs in every case.

The trade off to creating another layer for the business logic is that you have to actually encapsulate your code. If you're too aggressive, you might also get some duplication between your entities and your domain model (if your DB's relational semantics already take care of your buiness logic).

View

The view is the most brittle part of your app, as it is the most likely part to change.

It is also very hard to get business logic correct in your view, due to having to support all the various view state transitions.

It is extremely well known these days that you just don't do this :)

Repository

The issue here is one of maintenance and purity of abstraction. Violating this can confuse people and make your app hard to maintain.

From the P of EAA article on the Repository pattern:

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection

A repository is an abstraction that presents your data storage as a collection that holds domain objects.

No domain logic should reside in it. Instead, it should exist in your domain objects (by definition, as your business logic is your domain).

To do otherwise (to make your repository do double duty and also validate domain logic) would be a violation of SRP (Single Responsibility Principle), and would be a code smell.

You can have higher level domain objects that work with collections of domain objects to validate domain logic (such as dependencies within a collection of objects, size limits, etc). They will still use your repositories under the covers to do final storage/retrieval of domain objects, so they won't be doing double duty (so won't violate SRP).

Controller

The controller is also not a good place to put business logic. The controller's job is to mediate between the controller and the model.

The model is the domain, and the domain is your business logic.

Entities

You might consider putting domain data in entities.

But you must be careful when accessing navigation properties if the entities are attached, as you can trigger inadvertent DB queries or exceptions (depending on if your context is disposed or not). Detaching them is also a problem, as it destroys your object graph unless you explicitly reattach the objects to each other after detaching them from the context.

If you make separate domain model classes, you might consider treating entities as DTOs only.

Edit: IValidatableObject

I found out just now about a feature in Entity Framework 4.1 that you may want to check out: the IValidatableObject interface.

You can make your entities partial classes, and in the partial class, implement this interface. When you do, the Entity Framework will call Validate on save, and you can call Validate whenever it makes sense for you to do so.

This might help you avoid splitting your persistence model from your domain model in additional cases.

See this article: http://msdn.microsoft.com/en-us/data/gg193959

Side note: Views/View Models

In case you are thinking about it, I suggest you avoid the temptation to pass entities back to the view. It will break in a lot of cases (e.g. Javascript serialization to store view state), and cause unintentional DB queries in other cases. Pass back simple types instead (strings, ints, lists, hashsets, dictionaries, etc), or construct view model classes to pass to the view.

How to handle this routing?

5 votes

I have URL's like:

  • /nl/blog (shows overview of blog items)
  • /nl/blog/loont-lekker-koken-en-wordt-eerlijkheid-beloond (shows blog item with urltitle)
  • /nl/blog/waarom-liever-diëtist-dan-kok (shows blog item with urltitle)

for which I have defined routes:

  • A: route "nl/blog/{articlepage}" with constraint articlepage = @"\d"
  • B: route "nl/blog"
  • C: route "nl/blog/{urltitle}/{commentpage}" with constraint commentpage = @"\d"
  • D: route "nl/blog/{urltitle}"

Question 1: this works fine, but maybe there's a better solution with less routes?

Question 2: to add a new article, I have an action method AddArticle in BlogController. Of course, with the routes defined above, the url "/nl/blog/addarticle" would map to route D, where addarticle would be the urltitle which is not correct of course. Therefore I added the following route:

  • E: route "nl/blog/_{action}"

and so now the url "/nl/blog/_addarticle" maps to this route, and execute the correct action method. But I was wondering whether there is a better way to handle this?

Thanks for the advice.

Answers to my own questions:

For question one, I created a custom constraint IsOptionalOrMatchesRegEx:

public class IsOptionalOrMatchesRegEx : IRouteConstraint
{
    private readonly string _regEx;

    public IsOptionalOrMatchesRegEx(string regEx)
    {
        _regEx = regEx;
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        var valueToCompare = values[parameterName].ToString();
        if (string.IsNullOrEmpty(valueToCompare)) return true;
        return Regex.IsMatch(valueToCompare, _regEx);
    }
}

Then, routes A and B can be expressed in one route:

  • url: "nl/blog/{articlepage}"
  • defaultvalues: new { articlepage = UrlParameter.Optional }
  • constraints: new { articlepage = new IsOptionalOrMatchesRegEx(@"\d")

For question 2, I created an ExcludeConstraint:

public class ExcludeConstraint : IRouteConstraint
{
    private readonly List<string> _excludedList;

    public ExcludeConstraint(List<string> excludedList)
    {
        _excludedList = excludedList;
    }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        var valueToCompare = (string)values[parameterName];
        return !_excludedList.Contains(valueToCompare);            
    }
}

Route D could then be changed like:

  • url: "nl/blog/{urltitle}"
  • constraints: new { urltitle = new ExcludeConstraint(new List() { "addarticle", "addcomment", "gettags"}) }));

WCF Web Api as a subdomain of an asp.net mvc 3 app?

5 votes

I have an mvc app running on mydomain.com, and I have added a wcf web api to the web project.

I can access the rest service by going to mydomain.com/MyResource but I actually want MyResource to ONLY work if I go to api.myDomain.com/MyResource, and mydomain.com/MyResource to look for a controller called MyResourceController and throw an error if it didn't find it.

How can I do this?

You'll have to create a new web site in IIS to solve this and create two projects in your solution.

Asp.net MVC FileContentResult - prevent opening in browser

4 votes

One of my controller actions returns a file to the user. I would like the user to be presented with the download (open/save) dialog, regardless of the file type. This works fine when the file type is .doc, .docx, .xlsx, etc.., but when the file is .txt, .xps, .pdf (sometimes), or .html, it opens in the browser.

Is there a way I can prevent the file from opening in the browser, and only allow the user to open it in a separate window without navigating away from the current page?

The request for the file is made using jQuery's $.ajax({}).

Related: Having the browser handle the request and give the popup as opposed to the AJAX call receiving the conent of the file as a response string is explained by this ansewr, but this question addresses forcing the browser to handle the file in a certain way once it is received.

I don't think you can do this with a client-side command or setting. You would need to do something on the server so that it returns a content type of application/octet-stream for every file. Otherwise, the browser will look at the incoming file and decide what to do with it based on its own rules and capabilities.

If you can do this on your server, try setting the "Content-Disposition" header to "attachment; filename=whatever.xyz"

asp.net-mvc: razor '@' symbol in js file

2 votes

I have a java script function that uses the @Url.Content C# function, I want to move that method to my js file referenced from my view.

The problem is that java script doesn't "know" the @ symbol!

Is there a way to reference js file from view with "@" symbol? (I'm programming asp.net mvc razor project.)

Well I've just found a razor engine on nuget that does it! Solve @ syntax!
The owner blog and explanations about the package abilities
The Nuget package

What do you guys think about that library?