tags:

views:

514

answers:

2

I'm returning multiple shapes to a page and am using a ViewData class that I've created. The namespace of this class is:

namespace IntranetMvcAreas.Areas.Accounts.Views.ContractsControl.ViewData

which I'm not sure it correct. In the page I attempted:

Inherits="System.Web.Mvc.ViewPage<ViewData.ContractsViewData>"

But ViewData doesn't even resolve in intellisense, so I'm not sure what I'm doing wrong, but I can't get access to any of the available objects.

I'm also doing this in the controller function:

return View(new ContractsViewData(contracts, costCentres, userTerminals, serviceMapping, services));

which should provide that ViewData object in the view.

Any ideas?

EDIT

Here's my namespaces import in my web.config

<namespaces>
    <add namespace="IntranetMvcAreas.Areas.Accounts.Models"/>
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Routing" />
    <add namespace="System.Linq" />
    <add namespace="System.Collections.Generic" />
</namespaces>

I've moved ContractsViewData to the Models folder instead now.

UPDATE

I re-created the entire project and built it up from scratch just to double check. I'm using Phil Haack's AreaLib, I'm not sure if this makes any difference. Anyway, I've got a ViewModels folder which contains a ViewData class called ContractsControlViewData.cs which contains the following:

namespace Intranet.Areas.Accounts.ViewModels
{
  using Intranet.Areas.Accounts.Models;
  using System.Collections.Generic;

  public class ContractsControlViewData
  {
    public IEnumerable<Contract> Contracts { get; set; }
    public IEnumerable<tblCC_Contract_CC> tblCC_Contract_CCs { get; set; }
    public IEnumerable<tblCC_Contract_Data_Terminal> tblCC_Contract_Data_Terminals { get; set; }
    public IEnumerable<tblCC_CDT_Data_Service> tblCC_CDT_Data_Services { get; set; }
    public IEnumerable<tblCC_Data_Service> tblCC_Data_Services { get; set; }
  }
}

Then in my controller I have the following:

        public ActionResult DataContracts()
        {
          IEnumerable<Contract> contracts;

          using(ContractsControlDataContext db = new ContractsControlDataContext())
          {
            IMultipleResults results = db.procCC_Contract_Select(null, null, null, null, null, null);
            contracts = results.GetResult<Contract>();
          }

          return View(new ContractsControlViewData {
            Contracts = contracts,
            tblCC_Contract_CCs = null,
            tblCC_Contract_Data_Terminals = null,
            tblCC_CDT_Data_Services = null,
            tblCC_Data_Services = null
          });
        }

My web config has the following:

  <namespaces>
    <add namespace="Intranet.Areas.Accounts.ViewModels"/>
    <add namespace="System.Web.Mvc"/>
    <add namespace="System.Web.Mvc.Ajax"/>
    <add namespace="System.Web.Mvc.Html"/>
    <add namespace="System.Web.Routing"/>
    <add namespace="System.Linq"/>
    <add namespace="System.Collections.Generic"/>
  </namespaces>

My ContractsControl.design.cs has the following (because it doesn't work if you place it in the partial class:

[Function(Name = "dbo.procCC_Contract_Select")]
    [ResultType(typeof(Contract))]
    [ResultType(typeof(tblCC_Contract_CC))]
    [ResultType(typeof(tblCC_Contract_Data_Terminal))]
    [ResultType(typeof(tblCC_CDT_Data_Service))]
    [ResultType(typeof(tblCC_Data_Service))]
    public IMultipleResults procCC_Contract_Select(
        [Parameter(Name = "ContractID", DbType = "Int")] System.Nullable<int> contractID,
        [Parameter(Name = "ContractTypeID", DbType = "Int")] System.Nullable<int> contractTypeID,
        [Parameter(Name = "ResponsibilityKey", DbType = "Int")] System.Nullable<int> responsibilityKey,
        [Parameter(Name = "ExpenseType", DbType = "Char(4)")] string expenseType,
        [Parameter(Name = "SupplierID", DbType = "Int")] System.Nullable<int> supplierID,
        [Parameter(Name = "BusinessID", DbType = "Char(4)")] string businessID)
    {
      IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), contractID, contractTypeID, responsibilityKey, expenseType, supplierID, businessID);
      return (IMultipleResults)result.ReturnValue;
    }

Once I place the generic in my Inherits statement I no longer get access to ViewData. Additionally if I place the sproc function declaration in the partial class I can't do a build.

So I have got no idea. Personally I think it's a bug, but then having a stored procedure bring back multiple result sets isn't exactly great. In fact, it's horrible.

EDIT

The only thing I found that was relevant was this link. However, when I clear out the Application Settings and set it to false my *.designer.cs file is removed which means no classes from my dbml file are accessible.

**EDIT EDIT **

After re-implementing the model (again) and going with Ian's idea to add the following:

<PropertyGroup>
    <MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>

I now receive the following error:

Error   1 Could not load type 'System.Web.Mvc.ViewPage<ContractsControlViewData>'. D:\temp\Areas\Accounts\Views\ContractsControl\DataContracts.aspx 2 Intranet

However, I've tried with the fully qualified name, and I've also tried placing the ViewData class in the same folder as the View as well as removing the namespace to make sure it's available. It's not being seen for some reason, but at least it's a step closer perhaps? I'm guessing ViewData wasn't available in the view because the generic used in the inherits statement wasn't valid, which would explain that part of it.

Any further thoughts?

A: 

I had to do something similar this morning, to get the intellisense to work for I had to specify the full type definition.

Inherits="System.Web.Mvc.ViewPage<IntranetMvcAreas.Areas.Accounts.Views.ContractsControl.ViewData.ContractsViewData>"

You should then be able to access the shapes through the associated properties on your model property in the markup.

I hope I've understood the question properly and I hope this helps.

WestDiscGolf
The problem for me, more specifically is that ViewData doesn't even appear in intellisense for the page. It only appears if I get rid of the generic type inbetween < and >
Kezzer
Do you have the System.Web.Mvc dll imported in your solution?What namespaces are you importing in your web.config?
madcapnmckay
I've got the dll imported, but will check the web.config. Cheers!
WestDiscGolf
+2  A: 

Firstly you shouldn't have to fully qualify your namespace so the below will be ok.

Inherits="System.Web.Mvc.ViewPage<ContractsViewData>"

You will then need to import that namespace for the ViewModel to be accessible on the ViewData.Model property within the view.

I tend to create my viewmodels in the same namespace and then import this into all views by adding the below to my web.config.

<namespaces>
    <add namespace="IntranetMvcAreas.Areas.Accounts.Views.ContractsControl.ViewData"/>
</namespaces>

Alternatively you could import the namespace at the top of your page as follows.

<%@ Import Namespace="IntranetMvcAreas.Areas.Accounts.Views.ContractsControl.ViewData"%>

You can then access your model within your view as follows.

<%= Model.Property %>

Hope this helps.

EDIT

I would try and compile your views and see what the problem is. Open your project file in notepad and edit the xml as follows.

<PropertyGroup>
    <MvcBuildViews>true</MvcBuildViews>
</PropertyGroup>
madcapnmckay
Also, should my ViewData model be in the Views folder or the Model folder?
Kezzer
I don't think it matters where your ViewModel class is. Because its an import like any other in C# you can have the model classes in a separate assembly if you wish. For small projects I would create a ViewModels folder to separate them from the main Model classes but thats just me.
madcapnmckay
Okay, the only problem I'm having now is that the minute I use <ContractsViewData> as the generic type for the inherits statement at the top of my page I lose the use of ViewData. It no longer appears in intellisense with the error of "The name 'ViewData' does not exist in the current context." - so I can't find out anything about the model from this.
Kezzer
That's very strange. I have never seen that personally. ViewData is a property on the ViewPage class so all I can think is somehow it's not building the page as an instance of that class. Have you got this to work before? Id suspect something fishy with the web.config, maybe try creating a new project using the default template and experiement.
madcapnmckay
Most of it worked for me using a VB.NET project, but I'm running it as a C# project now, and I'm using Phil Haack's areas lib which adds to the complexity a bit. I'll try a few things first.
Kezzer