1

I have a view that was using a standard Model but now I need to add information from two different models on the page. I created a ViewModel after doing some research to handle this. Now I am getting an error when tring to show my view saying:

DataBinding: 'VirtualAuthtech.ViewModels.CMSCalculatorViewModel' does not contain a property with the name 'WORKCY'.

Here's my viewmodel

namespace VirtualAuthtech.ViewModels
{
    public class CMSCalculatorViewModel
    {
        public CPT CPT { get; set; }
        public GPCI GPCI { get; set; }
    }
}

CPT is the first model I was originally using and then I need to add GPCI

Here is the ActionResult for my view

public ActionResult _CMSCalculator()
        {
            string CPTCode = string.Empty;
            string MOD = string.Empty;
            string GPCIPayID = "31146";
            string GPCIYear = "2011";
            if (Request.Params["CPT1"] != null)
            {
                CPTCode = Request.Params["CPT1"];
                MOD = Request.Params["MOD"];
            }
            return PartialView("_CMSCalculatorPanel", (string.IsNullOrEmpty(CPTCode) ? null as CMSCalculatorViewModel : CPTDataHelper.GetCPTGPCI(CPTCode, MOD, GPCIPayID, GPCIYear)));
        }

Here is the method to get the data from my models

    public static CMSCalculatorViewModel GetCPTGPCI(string CPTCode, string MOD, string GPCIPayID, string GPCIYear)
    {
        using (var DB = new VADataContext())
        {
            var view = new CMSCalculatorViewModel();
            if (String.IsNullOrWhiteSpace(MOD))
            {
                view.CPT = (from cpt in DB.CPTs
                            where cpt.CPT1 == CPTCode
                            select cpt).FirstOrDefault<CPT>();
                view.GPCI = (from gpci in DB.GPCIs
                             where gpci.PAYID == GPCIPayID && gpci.YEAR == GPCIYear
                             select gpci).FirstOrDefault<GPCI>();
            }
            else
            {
                view.CPT = (from cpt in DB.CPTs
                            where cpt.CPT1 == CPTCode && cpt.MOD == MOD
                            select cpt).FirstOrDefault<CPT>();
                view.GPCI = (from gpci in DB.GPCIs
                             where gpci.PAYID == GPCIPayID && gpci.YEAR == GPCIYear
                             select gpci).FirstOrDefault<GPCI>();
            }
            return view;
        }
    }

Now my view is using the new ViewModel and I'm trying to display a field:

<div style='float:left; width: 35px; margin: 0; padding: 0; text-align: center; color: #094ab2'>@VirtualAuthtech.CallbackPanelHelper.GetFieldNumber(Model, "WORKCY")</div>

And I'm getting an error in this piece of code:

public static double GetFieldNumber(object data, string fieldName)
        {
            object text = DataBinder.Eval(data, fieldName);
            if (text == null || text.ToString() == string.Empty)
                return 0;
            double number = Convert.ToDouble(text);
            return number;
        }

It's saying my model does not contain the property of the field I'm looking for. Do I need to tell it to look in the CPT part of my view model?

This is the first ViewModel I've ever created so I might be going about this all wrong. Any help to send me in the right direction would be greatly appreciated!

Todd Skelton
  • 6,839
  • 3
  • 36
  • 48
  • I would say the error is accurate. Your model (CMSCalculatorViewModel) contains two properties, CPT and GPCI, neither of which are named "WORKCY". – Ben Finkel Oct 05 '12 at 19:42
  • WORKCY is a property of the CPT Model what do I need to change to make it aware of that? – Todd Skelton Oct 05 '12 at 19:55

2 Answers2

1

Why the call to GetFieldNumber? What would be wrong with the following line:

<div style='float:left; width: 35px; margin: 0; padding: 0; text-align: center; color: #094ab2'>@Model.CPT.WORKCY</div>

But if you have to use run-time binding, then maybe the line in your function should be:

object text = DataBinder.Eval((CMSCalculatorViewModel)data.CPT, fieldName);
Ben Finkel
  • 4,753
  • 7
  • 34
  • 49
  • I can't do this because it will be a null model to begin with. The field updates when a user selects an item from a grid based on his selection. There are also many more fields that will have logic behind them as well. – Todd Skelton Oct 05 '12 at 19:57
  • I updated the code, but it shouldn't matter that the object is NULL to start... as long as it's strongly typed you can reference the fields directly at design time versus run-time. – Ben Finkel Oct 05 '12 at 19:59
  • I tried your code and it said I couldn't do runtime databinding to null references. I will post a solution that worked but if you get one that doesn't involve making sure my model isn't null for every field please let me know. – Todd Skelton Oct 05 '12 at 20:11
  • The problem I have with your updated code is I will have to make a new set of Methods because my original methods are used in other pages with different models. If I tell it use data.CPT then it will no longer work on any other page. Thanks for your help with this. – Todd Skelton Oct 05 '12 at 20:17
  • Remember in MVC (the design pattern) your View should be aware of and specifically designated for the Model (or VieWModel in this case) so unless there is a specific reason for late-binding you ought to be able to design-time all of this and avoid the need to use Eval at all. – Ben Finkel Oct 05 '12 at 20:30
  • Okay, I figured out the problem here. It was trying to do it all at runtime because I was passing the viewmodel to a partial that these fields are located in. If I @using the model directly on the partial then I can use it at design time. – Todd Skelton Oct 05 '12 at 20:39
  • I've started putting in the data directly like you said I should, but I'm still getting an error saying that says "Cannot perform runtime binding on a null reference" – Todd Skelton Oct 05 '12 at 21:23
0

I was able to get it working using this code.

<div style='float:left; width: 35px; margin: 0; padding: 0; text-align: center; color: #094ab2'>@if(Model == null) { <text>0</text> } else { @VirtualAuthtech.CallbackPanelHelper.GetFieldNumber(Model.CPT, "WORKCY") }</div>

However, I have a lot of other fields in this view. I would rather not have to check if the model is null on every one of them. If you have another solution please share.

Todd Skelton
  • 6,839
  • 3
  • 36
  • 48
  • Looks good, but why don't you just set your Model to a new, blank, empty Model up front then you don't have to do late-binding? – Ben Finkel Oct 05 '12 at 20:28
  • I went ahead an initialized the Model to use the first item in the list that it will select anyway so it doesn't start as null. Now it's working without databinding. This seems like a much cleaner way to do it. Thanks. – Todd Skelton Oct 05 '12 at 22:59