Reputation: 33
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
Upvotes: 1
Views: 8526
Reputation: 239250
You can only use the For
methods with actual properties on your model (i.e. 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.
Upvotes: 2
Reputation: 1707
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;
}
}
Upvotes: 0
Reputation: 33815
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"} })
Upvotes: 2
Reputation: 507
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"} })
Upvotes: 1