简体   繁体   中英

Calling a method in Razor ASP.NET MVC

I am a newbie at MVC and having trouble displaying the result of a certain method in a view input field. I am not too sure if I am supposed to create the method in the cshtml or in a separate cs file.

I have used the @function tag to create my method in a cshtml file below

@functions{

    public int DaysCalc(DateTime first, DateTime second)
    {
        QuoteApp.Models.Quote ts = new QuoteApp.Models.Quote();
        ts.StartDate = first;
        ts.EndDate = second;

        int days;
        days = (second.Day - first.Day);
        return days;


    }

}

I am calling it this way in the cshtml file

 @Html.EditorFor(model =>model.DaysCalc(model.StartDate, model.EndDate), new { htmlAttributes = new { @class = "form-control", disabled = "disabled"} })

I get an error stating

Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.

Source Error:

Line 63:             @Html.LabelFor(model => model.noOfDays, htmlAttributes: new { @class = "control-label col-md-2" })
Line 64:             <div class="col-md-10">
Line 65:                 @Html.EditorFor(model =>@DaysCalc(model.StartDate, model.EndDate),new { htmlAttributes = new { @class = "form-control", disabled = "disabled"} })
Line 66:                 @Html.ValidationMessageFor(model => model.noOfDays, "", new { @class = "text-danger" })
Line 67:             </div>

Source File:   Line: 65 

You can only use the For methods with actual properties on your model (ie not functions). I'm not sure what you're actually trying to achieve by doing this, so I can't really help you further unless you update your question, but that explains your error at least.

EDIT

First and foremost, I need to point out that your date calculation is not correct. What if StartDate is 2014-06-30 and EndDate is 2014-07-01. Then the result of is going to 1 - 30 = -29 . I'm reasonably sure that's not what you're looking for. There's a method on DateTime just for this purpose:

TimeSpan difference = EndDate.Subtract(StartDate);

The result is a TimeSpan , which you can then call difference.Days to get the number of days involved. Also of note, there's a TotalDays property off TimeSpan that will return fractional days (whereas Days just returns whole days).

Next, for what it's worth, and since you're new to all this, the in-view Razor helpers are a nice novelty, but they're impractical to the point of being useless, and frankly, they violate MVC (the pattern, not the framework from Microsoft). If you need to do this type of calculation, the best place for it is on your model. You can implement a property like:

public int Days
{
    get
    {
        return EndDate.Subtract(StartDate).Days;
    }
}

However, that's read-only (there's no setter method), and if you're talking about using this as an input value, it doesn't make sense to have a read-only property backing it (unless, I guess, if you make it a read-only input, in which case it might as well just be plain-text). So, if this is something you intend to post back to you'll need to figure out what that means in terms of a setter. Honestly, I can't see what you would do with that because the only logical thing to do is have it set values for StartDate and EndDate , and you can't do that without some point of reference. You could require StartDate to be set, and then take a value for Days and then use that to calculate EndDate , but it all boils down to what your business requirements are.

If you want to use EditorFor, create a property that returns your calculated value.

public class YourModel
{
    public int CalculatedDays
    {
        get
        {
            QuoteApp.Models.Quote ts = new QuoteApp.Models.Quote();
            ts.StartDate = first;
            ts.EndDate = second;

            return (ts.EndDate - ts.StartDate);
        }
    }
}

@Html.EditorFor(model => model.CalculatedDays, new { htmlAttributes = new { @class = "form-control", disabled = "disabled"} })

Add the Days property to your view model and store the result of the DaysCalc on it.

Then you can use it like:

@Html.EditorFor(model =>model.Days, new { htmlAttributes = new { @class = "form-control", disabled = "disabled"} })

Try creating a property on your model (this is assuming you are using a typed model, not a dynamic one):

public int Days
{
    get {

        QuoteApp.Models.Quote ts = new QuoteApp.Models.Quote();
        ts.StartDate = StartDate;
        ts.EndDate = EndDate;

        int days;
        days = (EndDate.Day - StartDate.Day);
        return days;
    }
}

Usage:

@Html.EditorFor(model => model.Days, new { htmlAttributes = new { @class = "form-control", disabled = "disabled"} })

I'm not sure if EditorFor will work quite right with a readonly property or not, but it looks like you are just using it for display or some other purpose anyway?

Also, I'm not sure what you are using the Quote object for, since it doesn't appear you are doing anything with it other than creating it, so this could be possibly simplified into:

public int Days
{
    get {
        return EndDate.Day - StartDate.Day;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM