Best asp.net-mvc questions in June 2012

ASP.NET MVC - Database entities or ViewModels?

19 votes

I am currently working on an ASP.NET MVC project.

Some developers on the team want to bind the auto-generated database entities directly to the Views.

Other developers want to create tailor-made ViewModel's and bind those to the Views.

Objectively, what are the pros and cons of both approaches?

(By "database entities" I am referring to the auto generated classes that an ORM framework generates, such as LINQ to SQL, Entity Framework or LLBLGen).

Definitely use view models in your views, and use something like AutoMapper to create view models from entities easily.

Cons:

  1. Sometimes it feels like you are duplicating code, specifically, when the view model and the entity have the exact same properties

Pros:

  1. You often need to represent an object in a simpler format (often called flattening), but you need full fidelity on the server side. This allows you to transition between the two without mucking up your domain model with presentation cruft.
  2. Aggregate roots often have a lots of value objects and additional entities that are irrelevant to a specific view, and omitting them in a view model makes it easier to work with.
  3. Your entities will have lots of two way references that are sensible in terms of an API, but create pure hell when serializing them for JSON, XML, etc. View models will eliminate these circular references.
  4. You may often use the same entity but in different ways for different views. Trying to balance both needs on one type can create a huge mess.

What is the difference between an Azure Web Site and an Azure Web Role

9 votes

What are the material differences between the new Azure Web Sites and the traditional Azure Web Roles for an ASP.NET MVC application? What reason would I choose a "web site" over a "web role" or vice versa?

Let's assume that I would need equal capacity in either case (e.g. 2 small instances). The prices seem comparable other than the fact that there is a 33% temporary discount for web sites while they are in their preview period.

Are there things that I can do with a "web site" that are difficulty or impossible with a web role? For example, does it become easy to put multiple web sites in a single set of VMs using "web sites"? Do I lose anything with a "web site" vs a "web role"? Ability to fine tune IIS? Ability to use the Cache service locally?

Web Roles give you several features beyond Web Sites:

  • Ability to run elevated startup scripts to install apps, modify registry settings, install performance counters, fine-tune IIS, etc.
  • Ability to split an app up into tiers (maybe Web Role for front end, Worker Role for backend processing) and scale independently
  • Ability to RDP into your VM for debugging purposes.
  • Network isolation

Web Sites have advantages over Web Roles though:

  • Near-instant deployment
  • git + ftp support
  • Ability to roll out one of numerous CMS's (like WordPress, Joomla, etc.)
  • Use of SQL Database or MySQL

Here's a screengrab I just took from the gallery selection form: enter image description here

I think Web Sites are a great way to get up and running quickly, where you can move from shared to reserved resources. Once you outgrow this, you can then move up to Web Roles and expand as you need.

Best Repository Pattern for ASP.NET MVC

8 votes

I recently learned ASP.NET MVC (I love it). I'm working with a company that uses dependency injection to load a Repository instance in each request, and I'm familiar with using that repository.

But now I'm writing a couple of MVC applications of my own. I don't fully understand the hows and whys of the repository my company uses, and I'm trying to decide the best approach to implement data access.

I am using C# and Entity Framework (with all the latest versions).

I see three general approaches for handling data access.

  1. Regular DB context within a using statement each time I access data. This is simple and it works okay. However, if two locations need to read the same data within one request, the data must be read twice. (With a single repository per request, the same instance would be used in both places and I understand the second read would simply return the data from the first read.)

  2. A typical repository pattern. For reasons I don't understand, this typical pattern involves creating a wrapper class for every table used from the database. That seems wrong to me. In fact, since they are implemented also as interfaces, I'd technically be creating two wrapper classes for each table. EF creates tables for me. I don't believe this approach makes sense.

  3. There is also a generic repository pattern where a single repository class is created to serve all entity objects. This makes much more sense to me. But does it make sense to others? Is the link above the best approach?

I'd love to get some input from others on this topic. Are you writing your own repository, using one of those above, or doing something different altogether. Please share.

I have used a blend of #2 and #3, but I prefer a strict generic repository if possible (stricter than even suggested in the link for #3). #1 is no good because it plays poorly with unit testing.

If you have a smaller domain or need to constrict which entities that your domain allows to be queried, I suppose #2- or #3 that defines entity specific repository interfaces that themselves implement a generic repository- makes sense. However, I find it to be exhausting and unnecessary to write an interface and a concrete implementation for every entity I want to query. What good is public interface IFooRepository : IRepository<Foo> (again, unless I need to constrain developers to a set of allowed aggregate roots)?

I just define my generic repository interface, with Add, Remove, Get, GetDeferred, Count, and Find methods (Find returns an IQueryable interface allowing LINQ), create a concrete generic implementation, and call it a day. I rely heavily on Find and thus LINQ. If I need to use a specific query more than once, I use extension methods and write the query using LINQ.

This covers 95% of my persistence needs. If I need to perform some sort of persistence action that can't be done generically, I use a home-grown ICommand API. For example, say I'm working with NHibernate and I need to perform a complex query as part of my domain, or perhaps I need to do a bulk command. The API looks roughly like this:

// marker interface, mainly used as a generic constraint
public interface ICommand
{
}

// commands that return no result, or a non-query
public interface ICommandNoResult : ICommand
{
   void Execute();
}

// commands that return a result, either a scalar value or record set
public interface ICommandWithResult<TResult> : ICommand
{
   TResult Execute();
}

// a query command that executes a record set and returns the resulting entities as an enumeration.
public interface IQuery<TEntity> : ICommandWithResult<IEnumerable<TEntity>>
{
    int Count();
}

// used to create commands at runtime, looking up registered commands in an IoC container or service locator
public interface ICommandFactory
{
   TCommand Create<TCommand>() where TCommand : ICommand;
}

Now I can create an interface to represent a specific command.

public interface IAccountsWithBalanceQuery : IQuery<AccountWithBalance>
{
    Decimal MinimumBalance { get; set; }
}

I can create a concrete implementation and use raw SQL, NHibernate HQL, whatever, and register it with my service locator.

Now in my business logic I can do something like this:

var query = factory.Create<IAccountsWithBalanceQuery>();
query.MinimumBalance = 100.0;

var overdueAccounts = query.Execute();

You can also use a Specification pattern with IQuery to build meaningful, user-input-driven queries, rather than having an interface with million confusing properties, but that assumes you don't find the specification pattern confusing in its own right ;).

One last piece of the puzzle is when your repository needs to do specific pre- and -post repository operation. Now, you can very easily create an implementation of your generic repository for a specific entity, then override the relevant method(s) and do what you need to do, and update your IoC or service locator registration and be done with it.

However, sometimes this logic is cross-cutting and awkward to implement by overriding a repository method. So I created IRepositoryBehavior, which is basically an event sink. (Below is just a rough definition off the top of my head)

public interface IRepositoryBehavior
{
    void OnAdding(CancellableBehaviorContext context);
    void OnAdd(BehaviorContext context);

    void OnGetting(CancellableBehaviorContext context);
    void OnGet(BehaviorContext context);

    void OnRemoving(CancellableBehaviorContext context);
    void OnRemove(BehaviorContext context);

    void OnFinding(CancellableBehaviorContext context);
    void OnFind(BehaviorContext context);

    bool AppliesToEntityType(Type entityType);
}

Now, these behaviors can be anything. Auditing, security checking, soft-delete, enforcing domain constraints, validation, etc. I create a behavior, register it with the IoC or service locator, and modify my generic repository to take in a collection of registered IRepositoryBehaviors, and check each behavior against the current repository type and wrap the operation in the pre/post handlers for each applicable behavior.

Here's an example soft-delete behavior (soft-delete means that when someone asks to delete an entity, we just mark it as deleted so it can't be returned again, but is never actually physically removed).

public SoftDeleteBehavior : IRepositoryBehavior
{
   // omitted

   public bool AppliesToEntityType(Type entityType)
   {
       // check to see if type supports soft deleting
       return true;
   }

   public void OnRemoving(CancellableBehaviorContext context)
   {
        var entity = context.Entity as ISoftDeletable;
        entity.Deleted = true; // when the NHibernate session is flushed, the Deleted column will be updated

        context.Cancel = true; // set this to true to make sure the repository doesn't physically delete the entity.
   }
}

Yes, this is basically a simplified and abstracted implementation of NHibernate's event listeners, but that's why I like it. A) I can unit test a behavior without bringing NHibernate into the picture B) I can use these behaviors outside of NHibernate (say the repository is client implementation that wraps REST service calls) C) NH's event listeners can be a real pain in the ass ;)

is there an asp.net fiddle?

7 votes

Similar to jsfiddle, is there an asp.net fiddle website for us to share asp.net code fiddles? It'll greatly help asp.net developers. the current way to post asp.net code on SO is not so reader friendly. I hope there's something out there to make this easier. If there isn't anything like that (as i did some search but can't find one). Is this even something technically possible to be developed since c# is not a late binding language.

You could use something like compilr.com, It requires an account to create projects but people can view it anonymously. It's pretty neat.

Example: http://compilr.com/cravecode/test-share/main.cs

UPDATE

I'd also checkout coderun.com/ide

AntiForgeryToken deprecated in ASP.Net MVC 4 RC

6 votes

I just installed ASP.Net MVC 4 RC to replace ASP.Net MVC 4 beta. When trying to run an existing application I'm getting an error message that AntiForgeryToken has been deprecated. Here's my code:

using (Html.BeginForm("", "", FormMethod.Post, new { id = "MonthElectionForm" }))
{
    @Html.AntiForgeryToken("AddEditMonthElection")
}

---- UPDATE ---

ASP.Net MVC 4 RC has made the Salt property obsolete for ValidateAntiForgeryToken attribute and AntiForgeryToken html helper. So, now my code looks like this:

controller:

        [HttpPost]
        [ValidateAntiForgeryToken]
        public JsonResult CreateCompany(CompanyDataEntryViewModel modelData)
       {...}

form:

@using (Html.BeginForm("", "", FormMethod.Post, new { id = "CreateCompanyDataEntryForm" }))
{
    @Html.AntiForgeryToken()
...
}

Looking at generated HTML, AntiForgeryToken still generates a hidden field and provides an encrypted value. My action still works too. But I've lost the ability to designate a key to use in the encryption process. I'm not too sure how the process works, but before I can tell I was setting the salt value on the action and on the form. The values had to match in order for the action to accept the post. So, how do you set the salt value now? I think it has something to do with AntiForgeryConfig AdditionalDataProvider but I cannot find anything googling on how to use AntiForgeryConfig AdditionalDataProvider. Please help.

Thanks

Setting the salt parameter is unnecessary and didn't provide any additional protection, so we removed support for it.

Please see my response at How to choose a salt value for ValidateAntiForgeryToken for more information.

Dynamically extending features of an application?

6 votes

I recently came across a way to develop pluggable application modules when using ASP.NET MVC3/4 and I loved the simplicity of the approach. Currently, I have my applications structured as follows:

enter image description here

Therefore, anyone wanting to develop an extension for my application, follows the approach from the above tutorial and creates an extension that stays in the Areas folder. I figure that when new Areas (created as new projects) are added, .pdb files are created and placed in the bin directory. My question is this:

  • How does one distribute the Areas as pluggable modules?
  • How do I change the following code so that when someone drops a new Area into the bin folder, the application automatically picks it up and creates a link? And what should the plugin author do to enable this?

In my _Layout.cshtml (global shared layout), I do the following to construct the links:

<ul>
      <li>@Html.ActionLink("Area1", "Index", "Area1", new { Area = "Area1" }, null)</li>
      <li>@Html.ActionLink("Area2", "Index", "Area2", new { Area = "Area2" }, null)</li>
      <li>@Html.ActionLink("Area3", "Index", "Area3", new { Area = "Area3" }, null)</li>
</ul>

For simplicity, assume that the area names are unique. Any suggestions on how to do this?

How does one distribute the Areas as pluggable modules?

Don't create the Areas in the hosting web app, but create separate projects, that compile to separate dll's. Copy the dll's to any web app where you want to use it. Remember to set all static files as "EmbeddedResource".

How do I change the following code so that when someone drops a new Area into the bin folder, the application automatically picks it up and creates a link? And what should the plugin author do to enable this?

You can use MvcContrib PortableAreaRegistration's "Bus" to send messages, commands from the portable area to anyone on the 'bus'. That can be the hosting web app, or in theory independent Area's can send message to each other.

Created two crude, but functional demo of this, code on github:

MVC3 version:

https://github.com/AkosLukacs/PluggablePortableAreas

MVC4 RC version:

https://github.com/AkosLukacs/PluggablePortableAreasMVC4

First, you define a message that can carry the information you need. Just a POCO that has some properties (PluggablePortableAreas.Common\RegisterAreaMessage.cs):

public class RegisterAreaMessage : IEventMessage
{
    public string LinkText { get; private set; }
    public string AreaName { get; private set; }
    public string ControllerName { get; private set; }
    public string ActionName { get; private set; }
    //...
}

Create a handler for that message type (PluggablePortableAreas.Common\RegisterAreaEventHandler.cs):

public class RegisterAreaEventHandler : MessageHandler<RegisterAreaMessage>{}

In this case, the MessageHandler just adds the received messages to a static ConcurrentBag<RegisterAreaMessage>. You can use DI, if you want to, but wanted to keep it simple.

You can send the message from the portable area like this (Areas\DemoArea1\Areas\Demo1\Demo1AreaRegistration.cs):

 //the portable area sends a message to the 'bus'
 bus.Send(new RegisterAreaMessage("Link to the Demo area", AreaName, DefaultController, DefaultAction));

The dynamically added links are displayed by iterating over the collection of messages(PluggablePortableAreas.Web\Views\Shared_Layout.cshtml):

                @foreach(var sor in PluggablePortableAreas.Common.RegisterAreaEventHandler.RegisteredAreas) {
                <li>@Html.ActionLink(sor.LinkText, sor.ActionName, sor.ControllerName, new{Area=sor.AreaName}, null)</li>
                }

One more thing to take care of: Use "fully qualified" Area names. If you don't specify the area name explicitly, MVC assumes it's the current area. No problems without areas, but the second will point to "/path_to_your_app/CurrentArea/Home" instead of "/path_to_your_app/Home".

<li>@Html.ActionLink("Home", "Index", "Home", new { Area = "" }, null)</li>
<li>@Html.ActionLink("I don't work from the portable area!", "Index", "Home")</li>

Even one more thing to note!

The development server in VS feels a bit "erratic", sometimes the portable area doesn't load. Works reliably in full IIS tho...

Using Dependency Injection in ASP.NET MVC3 Model Binder

5 votes

I'm working on MVC3 website, trying to use Ninject to resolve my dependencies. I have the following scenario:

public class UserModelBinder : IModelBinder
{
    //[Inject]
    public UserDataService userData { get; set; }

    public object BindModel(
        ControllerContext controllerContext,
        ModelBindingContext bindingContext)
    {
        Guid UserID =
            (Guid)Membership.GetUser().ProviderUserKey;

        //userDataService = DependencyResolver.Current
        //    .GetService<UserDataService>();

        User user = userDataService.GetUser(UserID);

        return user;
    }
}

noticed the commented lines of code?

I do register the binder in Global.asax as

ModelBinders.Binders[typeof(User)] = new UserModelBinder();

So I can't really do injection through the construction.

UserDataService has a chain of dependencies: UserDataService -> UserRepository -> Context. So it would be good to use Ninject here.

The problem is, when I uncomment [Inject] above userData declaration, and try getting Ninject to inject object as a parameter, it does not work for some reason: I get null reference exceptions.

(could it be that UserDataService does not have an interface and I'm binding the object to itself: kernel.Bind<UserDataService>().ToSelf(); ??)

I have another commented line in the code:

userDataService = DependencyResolver.Current
    .GetService<UserDataService>();

When this is uncommented, the set up works, I get correct objects inserted, but now we depend on DependencyResolver and that is not much better than saying userDataService = new UserDataService()

Am I missing something? Is there another way to inject an object as a parameter and not introducing dependency on Ninject or DependencyResolver?

A model binder should just do data conversion and should not depend on any services and certainly not trigger any database communication. That should be done in another part of your application. Your Action method should just take a Guid userId and you should call userDataService.GetUser(UserID); from within your controls (or in a lowel layer, for instance, inside a business command). By doing this, your problem will not exist.

DTO Pattern + Lazy Loading + Entity Framework + ASP.Net MVC + Auto Mapper

5 votes

Firstly, Sorry For lengthy question but I have to give some underlying information.

We are creating an Application which uses ASP.net MVC, JQuery Templates, Entity Framework, WCF and we used POCO as our domain layer. In our application, there is a WCF Services Layer to exchange data with ASP.net MVC application and it uses Data Transfer Objects (DTOs) from WCF to MVC.

Furthermore, the application uses Lazy Loading in Entity Framework by using AutoMapper when converting Domain-TO-DTOs in our WCF Service Layer.

Our Backend Architecture as follows (WCF Services -> Managers -> Repository -> Entity Framework(POCO))

In our application, we don't use View Models as we don't want another mapping layer for MVC application and we use only DTOs as View Models.

Generally, we have Normal and Lite DTOs for domain such as Customer, CustomerLite, etc (Lite object is having few properties than Normal).

Now we are having some difficulties with DTOs because our DTO structure is becoming more complex and when we think maintainability (with general Hierarchical structure of DTOs) we lose Performance.

For example,

We have Customer View page and our DTO hierarchy as follows

 public class CustomerViewDetailsDTO
 {
   public CustomerLiteDto Customer{get;set;}
   public OrderLiteDto Order{get;set;}
   public AddressLiteDto Address{get;set;}
 }

In this case we don't want some fields of OrderLiteDto for this view. But some other view needs that fields, so in order to facilitates that it we use that structure.

When it comes to Auto Mapping, we map CustomerViewDetailsDTO and we will get additional data (which is not required for particular view) from Lazy Loading (Entity Framework).

My Questions:

  1. Is there any mechanism that we can use for improving performance while considering the maintainability?

  2. Is it possible to use Automapper with more map view based mapping functions for same DTO ?

First of don't use Lazy Loading as probably it will result in Select N+1 problems or similar.

Select N + 1 is a data access anti-pattern where the database is accessed in a suboptimal way.

In other words, using lazy loading without eager loading collections causes Entity Framework to go to the database and bring the results back one row at a time.

Use jsRender for templates as it's much faster than JQuery Templates: Render Bemchmark and here's an nice info for how to use it: Reducing JavaScript Code Using jsRender Templates in HTML5 Applications

Generally, we have Normal and Lite DTOs for domain such as Customer, CustomerLite, etc (Lite object is having few properties than Normal).

Your normal DTO is probably a ViewModel as ViewModels may or may not map one to one to DTOs, and ViewModels often contain logic pushed back from the view, or help out with pushing data back to the Model on a user's response. DTOs don't have any behavior and their purpose is to reduce the number of calls between tiers of the application.

Is there any mechanism that we can use for improving performance while considering the maintainability?

Use one ViewModel for one view and you won't have to worry about maintainability. Personally i usually create an abtract class that is a base, and for edit,create or list i inherit that class and add properties that are specific for a view. So for an example Create view doesn't need PropertyId (as someone can hijack your post and post it) so only Edit and List ViewModels have PropertyId property exposed.

Is it possible to use Automapper with more map view based mapping functions for same DTO ?

You can use AutoMapper to define every map, but the question is, how complicated the map will be. Using one ViewModel per view and your maps will be simple to write and maintain. I must point out that it is not recommended to use Automapper in the data access code as:

One downside of AutoMapper is that projection from domain objects still forces the entire domain object to be queried and loaded.

Source: Autoprojecting LINQ queries

You can use a set of extension that are limited as of now to speed up your mapping in data access code: Stop using AutoMapper in your Data Access Code

Regards

Creating a new controller class in Visual Studio with MVC?

5 votes

When I create a new controller in Visual Studio with MVC It generate automatically the following code :

public class Default1Controller : Controller
{
    //
    // GET: /Default1/

    public ActionResult Index()
    {
        return View();
    }

}

My Default1Controller inherit from Controller but I work with a BaseController class and I always have to remember to change the inheritance. Is it possible to Is it possible to modify or create a new template to automatically generate a more specific code for my project?

public class Default1Controller : BaseController
{
    //
    // GET: /Default1/

    public ActionResult Index()
    {
        return View();
    }

}

Thank you,

You have to modify the T4 template that's at the basis of the "Add controller" command.

Go to \Microsoft Visual Studio 11.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC 3\CodeTemplates\AddController\ (replace with your version of VS and MCV) and modify the Controller.tt

The line public class <#= mvcHost.ControllerName #> : Controller should become public class <#= mvcHost.ControllerName #> : BaseController

More details can be found on Scott Hanselman's blog

Model meaning in MVC

5 votes

Why is MODEL in ASP.NET MVC sometimes used as part of an application that talks to a database like here and sometimes as a business object that "travels" across applications delivering data like here?

MVC has evolved in different directions since its Smalltalk beginnings to the point where it is often used to describe very disparate architectures, as you've discovered.

Martin Fowler blogs about the evolution of MVC here. http://martinfowler.com/eaaDev/uiArchs.html

There is an explanation of the differences between MVC, MVP and MVVM here: http://joel.inpointform.net/software-development/mvvm-vs-mvp-vs-mvc-the-differences-explained/

My 10c:

Many examples of ASP.NET MVC 3 are more closely aligned to the MVVM pattern than MVC. In MVVM, ViewModels are tailored for the data specifics of each View (i.e. 'ViewModels' are not merely domain models, but are decorated with View / Presentation Tier concerns such as validation rules, field prompts / names, field visibility etc).

(Back to MVC) In smaller data centric projects without much need for back end tiering, M can be as simple as an ORM model (e.g. an .EDMX with some autogenerated POCOs) with a few rules. In this case MVC could just about be regarded as an application architecture.

But in larger projects using MVC, the original (Smalltalk) 'M' of model is now split up into several other layers, e.g. domain entities, service facades, Service (e.g. SOA), Business, and Data Tiers, etc (so here, M VC is a presentation tier pattern, and M is the rest of your system). So for example in such a project, the 'Models' folder of your MVC project could simply be proxied service references and proxied domain entities used to communicate with the 'back end' of your system, or even an abstraction of this communication (e.g. see the service agent / service facades used in the Composite Application Block).

Model object incomplete when try to update

5 votes

I have the following action methods:

public ActionResult ProfileSettings()
        {
            Context con = new Context();
            ProfileSettingsViewModel model = new ProfileSettingsViewModel();
            model.Cities = con.Cities.ToList();
            model.Countries = con.Countries.ToList();
            model.UserProfile = con.Users.Find(Membership.GetUser().ProviderUserKey);
            return View(model); // Here model is full with all needed data
        }

        [HttpPost]
        public ActionResult ProfileSettings(ProfileSettingsViewModel model)
        {
            // Passed model is not good
            Context con = new Context();

            con.Entry(model.UserProfile).State = EntityState.Modified;
            con.SaveChanges();

            return RedirectToAction("Index", "Home");
        }

@using (Html.BeginForm("ProfileSettings", "User", FormMethod.Post, new { id = "submitProfile" }))
        {
            <li>
                <label>
                    First Name</label>
                @Html.TextBoxFor(a => a.UserProfile.FirstName)
            </li>
            <li>
                <label>
                    Last Name</label>
                @Html.TextBoxFor(a => a.UserProfile.LastName)
            </li>
...
<input type="submit" value="Save" />
...

When I hit submit received model in POST method is incomplete. It contains FirstName, LastName etc. But UserID is null. So I can't update object. What am I doing wrong here?

MVC reconstructs your model only based on what's coming in the request. In your particular case, you are only submitting the FirstName and the LastName, because those are the only @Html.TextBoxFor() calls included in your View. MVC models don't behave like ViewState, it isn't stored anywhere.

You also don't want to include your entire Entity in your view-model. If all you need is the ID then that should be all you include. Then you'd load your entity again from your DAL, update the properties that need to be altered, and then save your changes.

How to pass datetime from view to controller in asp.net MVC

5 votes

Am trying to pass below data form my view to controller.

Edited

<script type="text/javascript">
  var pathname = 'http://' + window.location.host;
  var Student = [
  { Name: "Vijay", ID: 1, DOB: "2010-12-09T08:00:00.000Z" },
  { Name: "Anand", ID: 2, DOB: "2010-12-09T08:00:00.000Z" }
  ];

  $.ajax({
    url: pathname + "/Home/UpadetStu",
    type: "POST",
    dataType: "json",
    data: JSON.stringify(Student),
    contentType: "application/json; charset=utf-8",
    success: function (result) { }, 
    failure: function (r, e, s) { alert(e); } 
  });

</script>



   [ObjectFilter(Param = "stuData", RootType = typeof(Stu[]))]
    public JsonResult UpadetStu(Stu[] stuData)
    {
        return this.Json(new { success = true });
    }

[DataContract]
public class Stu
{
    [DataMember]
    public string Name { get; set; }

    [DataMember]
    public int ID { get; set; }

    [DataMember]
    public DateTime? DOB { get; set; }

}

But in the controller am getting null for Name and ID , default datetime for DOB, I found that there is problem in passing datetime. Is there any better way to pass datetime from view to controller? do i miss any parsing?

The problem is Thu Dec 9 13:30:00 UTC+0530 2010 can't be parsed into a valid datetime object in c#. You can try that by simply calling DateTime.Parse("Thu Dec 9 13:30:00 UTC+0530 2010") it will fail.

I would suggest that instead of returning that date format from the server you can better return the ISO 8601 format that looks like 2010-12-09T08:00:00.000Z.

You can easily convert the long datetime format into ISO 8601 from javascript by,

new Date("Thu Dec 9 13:30:00 UTC+0530 2010").toJSON();

If you are using JSON.NET library you can easily control the way in which the datetimes have to be serialized.

UPDATE:

<script type="text/javascript">

  var Student = [
  { Name: "Vijay", ID: 1, DOB: "2010-12-09T08:00:00.000Z" },
  { Name: "Anand", ID: 2, DOB: "2010-12-09T08:00:00.000Z" }
  ];

  $.ajax({
    url: "/Home/Index",
    type: "POST",
    dataType: "json",
    data: JSON.stringify(Student),
    contentType: "application/json; charset=utf-8",
    success: function (result) { }, 
    failure: function (r, e, s) { alert(e); } 
  });

</script>

[HttpPost]
public ActionResult Index(Student[] students)
{
  ...
}

Database Validation Errors. Allow nullable value in one table but not in related (normalized) table

5 votes

I have been looking for an answer to this for 2 days now. I'm not even sure exactly what is wrong, but I think I may have pinpointed the possible culprit.

My program is a database tracker/manager that will keep track of the equipment at my company. The user can query for, create, and edit equipment. Right now, querying the database works, but when I try to add to or update the database the program throws Validation errors (I'll get into this more below).

I have an equipment class that has many nullable attributes (because the user may not know many of these properties when creating a new entry, we left almost all the attributes nullable) and is connected to (using foreign keys and lazy loading/"virtual") to a few other tables that were made to help normalize the database.

Here is some abreviated code to help:

Equipment Model:

public class Equipment
{
    public int EquipmentId { get; set; } //required

    public string Company { get; set; } //required

    public bool Verified { get; set; } //required

    (...other non-required attributes...)


    //The following two attributes are where my problems are I believe
    [ForeignKey("PAU")]
    public int PAUId { get; set; } //required and Foreign Key    

    //This is not required (but is FK to the related table) if the user doesn't know
    [ForeignKey("Division")]
    public Nullable<int> DivisionId { get; set; }


    //These are the lazy loading connections to the other tables in the database

    public virtual Division Division { get; set; }

    public virtual PAU PAU { get; set; }
}

Division Model: This table only contains the 5 different divisions at our company and the related IDs.

public class Division
{
    public Division()
    {
        this.Equipments = new HashSet<Equipment>();
    }

    //These are non-nullable/required fields
    public int DivisionId { get; set; }
    public string DivisionName { get; set; }

    public virtual ICollection<Equipment> Equipments { get; set; }
}

PAU Model: This model contains the PAU#s and the related description and ID.

public class PAU
{
    public PAU()
    {
        this.Equipments = new HashSet<Equipment>();
    }

    //These are non-nullable/required fields
    public int PAUId { get; set; }
    public string PAUNumber { get; set; }
    public string PAUDescription { get; set; }

    public virtual ICollection<Equipment> Equipments { get; set; }
}

Equipment Controller:

public class EquipmentController : Controller
{
    TLCP_DEVEntities4 db = new TLCP_DEVEntities4();

    (...)

    public ActionResult Edit(int id)         
    {
        ViewData["divisions"] = new SelectList(db.Equipments.
                                OrderBy(x => x.Division.DivisionName).
                                Select(x => x.Division).ToList().
                                Distinct(), "DivisionId", "DivisionName");

        ViewData["PAUNumbers"] = new SelectList(db.Equipments.
                                 OrderBy(x => x.PAU.PAUNumber).
                                 Select(x => x.PAU).ToList().
                                 Distinct(), "PAUId", "PAUNumber");

        return View(db.Equipments.Find(id)); 
    }

    [HttpPost]
    public ActionResult Edit(Equipment equipment)
    {
        if (ModelState.IsValid)
        {
            db.Entry(equipment).State = EntityState.Modified;                    
            db.SaveChanges();     //fails here                                     
            return RedirectToAction("Maintenance"); 
        }

        ViewData["divisions"] = new SelectList(db.Equipments.
                                OrderBy(x => x.Division.DivisionName).
                                Select(x => x.Division).ToList().
                                Distinct(), "DivisionId", "DivisionName");

        ViewData["PAUNumbers"] = new SelectList(db.Equipments.
                                 OrderBy(x => x.PAU.PAUNumber).
                                 Select(x => x.PAU).ToList().
                                 Distinct(), "PAUId", "PAUNumber");

        return View(equipment);
    }

    public ActionResult AddEquipment()
    {
        ViewData["divisions"] = new SelectList(db.Equipments.
                                OrderBy(x => x.Division.DivisionName).
                                Select(x => x.Division).ToList().
                                Distinct(), "DivisionId", "DivisionName");

        ViewData["PAUNumbers"] = new SelectList(db.Equipments.
                                 OrderBy(x => x.PAU.PAUNumber).
                                 Select(x => x.PAU).ToList().
                                 Distinct(), "PAUId", "PAUNumber");

        return View();
    }

    public ActionResult AddEquipment(Equipment equipment)
    {
        try
        {
            db.Equipments.Add(equipment);
            db.SaveChanges();

            return RedirectToAction("Maintenance"); 
        }
        catch (Exception ex)
        {

            ViewData["divisions"] = new SelectList(db.Equipments.
                                    OrderBy(x => x.Division.DivisionName).
                                    Select(x => x.Division).ToList().
                                    Distinct(), "DivisionId", "DivisionName");

            ViewData["PAUNumbers"] = new SelectList(db.Equipments.
                                 OrderBy(x => x.PAU.PAUNumber).
                                 Select(x => x.PAU).ToList().
                                 Distinct(), "PAUId", "PAUNumber");

            return View();
        }
    }

    (...)
}

In the views I have dropdown lists that for these attributes that are populated with the possible options already in the database (stored in ViewData above). I have tried a couple different ways of storing this data into my model, but this way seems to work the best:

<%: Html.DropDownListFor(model => model.DivisionId,
       ViewData["divisions"] as SelectList, "")%>

Ok so after a lot of debugging, the problem seems to be because the lazy loaded properties have null attributes, which are not allowed in their tables. My examples will be dealing more with creating new equipment objects, though I believe the problem is the same for editing them.

Division Example: So DivisionId in the Equipment class can be null (either user doesn't know or equipment doesn't belong to specific division), and the Equipment table/class doesn't complain about that. But when I try to SaveChanges(), the program complains becuase the virtual Division object is null (has the default DivisionId of 0 and a null DivisionName). Since Equipment.DivisionId is null, I don't want to be updating the Division table for this Equipment object. Is there a way to get around this? Should I not be lazy loading?

PAU Example: Since PAUId is a required attribute for all Equipment objects, but as in the Division Example, PAU.PAUNumber and PAU.PAUDescription are null (and PAU.PAUId is the default 0) causing an error. This is just like the first one, but with the required attribute (so I am not sure if it needs to be handled differently).

So I am not really sure how to fix this problem.

  • Is lazy loading the issue since I only want to connect my Equipment object to those other tables if the Id/Foreign Key is not null?

  • Is there some method I can call that would update the equipment object's values from the other tables based on the Id's? Is it a method that I need to create myself?

  • If I get rid of lazy loading, could you explain how I should write my queries so I can still get access to the normalized data (like DivisionName)?

I apologize for the super long post. I just didn't want to miss anything that may be important.

Edit

I have a rough solution to the PAU Example (but I don't think it works for the Division Example because of allowing nulls within Equipment but not the individual tables).

public ActionResult AddEquipment(Equipment equipment)
    {
        try
        {
            equipment.PAU.PAUId = equipment.PAUId;
            equipment.PAU.PAUNumber = db.PAUs.Find(equipment.PAUId).PAUNumber;
            equipment.PAU.PAUDescription = db.PAUs.Find(equipment.PAUId).PAUDescription;


        (...)

    }

It's not very elegant though. I tried looking at a tutorial about reflection, but it didn't really make sense. If that would be a more elegant solution, could someone try explaining that?

I'm still looking for a solution for the Division Example (since Equipment.DivisionId is nullable but Division.DivisionId is not nullable this doesn't work), so any help on either this or a more elegant solution to the above would be greatly appreciated!

There was a part another part of my code that was acting odd which caused the error. I appreciate all your help! Thanks!

ASP.NET MVC 3 Structure - Go to view in another project

4 votes

I've got the following project setup

Project A (main)

  1. Business
  2. Data
  3. View (asp.net mvc 3 project)

Project N

  1. Business
  2. Data
  3. View (asp.net mvc 3 project)

How can I call from Project A the View in Project N and from N back to A. Essentially what I'm trying to do is package each Project N to have its own individual MVC as it comes from different sources and plug it in to the main project and then just have it navigate to the correct view.

Can this be done? Or is there a better way to do this?

I do sugest another approach if possible. if I understood correctly, those projects are somehow ike plugins but they are not standalone applications.Also they now about each others so they are coupled. It's, let's say tricky, but I would use only 1 asp.net mvc project (the web ui). All the UI bits which belong to other projects I'd make them helpers (pretty much widgets). This means, that each project contains only the helpers which will be used to construct a view.

I think it's a bit of an architectural problem if you only want to keep the views in each project just for the sake of hosting them in a different assembly. Going the widgets' way it might seem mkore work, but I think you gain the most control and the separation level you want. The only thing is you don't have full Views defined, but why you would want to have full Views (partials, layouts) in separate places if they will be used in one place only?!

Now, if each project is indeed a plugin, independent of other plugins, then going with compiled views is the best way. But if Project B knows about the view of Project N, then I think the above solution is more suitable. That or the whole app is too over engineered. Separation is good when it doesn't create a whole new jungle to navigate it.

MVC extending controller to have ajax-aware Redirect functionality

4 votes

Hi I am learning Ajax + MVC. I figured it would be nice for the Controller to automatically handle ajax-aware Redirect(). After some digging, I found the code from this link. The code below is totally transparent to user, a user can just call Redirect(someUrlString) without needing to worry about difference between normal/ajax calls. Makes it very neat and cool.

public abstract class BaseController : System.Web.Mvc.Controller {
    //turn into ajax aware redirect
    protected override RedirectResult Redirect(string url) {
        return new AjaxAwareRedirectResult(url);
    }
}

and ...

public class AjaxAwareRedirectResult : RedirectResult {
    public AjaxAwareRedirectResult(string url) : base(url) { }
    public override void ExecuteResult(ControllerContext context) {
        if (context.RequestContext.HttpContext.Request.IsAjaxRequest()) {
            string desturl = UrlHelper.GenerateContentUrl(Url, context.HttpContext);
            JavaScriptResult result = new JavaScriptResult() { 
                                      Script = "window.location='" + desturl + "';" };
            result.ExecuteResult(context);
        }
        else { base.ExecuteResult(context); }
    }
}

However, it is not complete. Challenge is:

RedirectToRouteResult RedirectToAction(ActionResult result)

is not there yet (Very handy especially for T4MVC).

As I am still new to MVC, I tried, but I am not knowledgeable enough to sufficiently figure out how to write this myself. Could any of you experts please help me with this? so I can learn it from your code? Thank you very much.

Here is the quick simple solution I use for Ajax aware redirection in my project..

  1. Create a class AjaxRedirectAttribute for action.

        public class AjaxRedirectAttribute : ActionFilterAttribute
        {
            public override void OnActionExecuted(ActionExecutedContext filterContext)
            {
                var result = filterContext.Result as RedirectResult;
                if (result != null && filterContext.HttpContext.Request.IsAjaxRequest())
                {
                    string destinationUrl = UrlHelper.GenerateContentUrl(result.Url, filterContext.HttpContext);
                    filterContext.Result = new JavaScriptResult()
                    {
                        Script = "window.location = '" + destinationUrl + "';"
                    };
                }
            }
        }
    
  2. User this attribute as below to either redirect to other page or to return some result from action.

    [AjaxRedirect]
    public ActionResult MyAction(FormCollection frmcol)
    {
        // some code here
        if (UserId != 0)
        {
            return Redirect(this.Url.Action("Action", "Controller"));
        }
        else
        {
            return Content("Error message here.");
        }
    }
    

How do I retrieve the VALUE of the object's property that is passed to my custom EditorFor from the view?

4 votes

System.Web.Mvc has an HtmlHelper that contains a method called EditorFor that renders the editing control associated with a data type in a view.

Im trying to create my own EditorFor method by extending the ASP.NET MVC 2 HtmlHelper. I have the following:

    public static string EditorForNew<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> item)
    {
        string value = "";
        string name = item.ToString(); // THIS IS CORRECTED IN MY COMMENT TO THE ANSWER BELOW!
        Type type = typeof(TProperty);

        if (type == typeof(int) || type == typeof(int?) || type == typeof(double) || type == typeof(double?) || type == typeof(decimal) || type == typeof(decimal?) || type == typeof(float) || type == typeof(float?))
        {
            return helper.TextBox(name, value, new { @class = "number" }).ToString();
        }
        else
        {
            return helper.TextBox(name, value).ToString();
        }
    }

Can anyone explain how I retrieve the VALUE of the object's property that is passed to this from the view?

You need to use a ModelMetadata:

ModelMetadata metadata = ModelMetadata.FromLambdaExpression(item, helper.ViewData);

You can then get the value from the metadata.Model property.

MVC Route Segment with a Question Mark?

4 votes

In this article by Sam Saffron, he mentions that Stack Overflow has a route that looks like this:

questions/{id}/{title?} 

Is that a typo? What does that question mark do?

From http://maproutes.codeplex.com/:

[Url("store/{category?}")]
public ActionResult Products(string category)
{
    return View();
}

'?' sign at the end of {category?} parameter means that it's optional. UrlParameter.Optional will be a default value for it.