Display readonly text with MVC Model - c#

I have an MVC Model, with a property defined as:
[DisplayName("Service Version")]
public string ServiceVersion { get; set; }
On the screen, I want it to display as:
Service Version: 0.1
'ServiceVersion' has the version number.
In the view, I have:
#model Main_UI.Models.HomeModel
And then:
#Html.LabelFor(m=>m.ServiceVersion) #Html.DisplayText(Model.ServiceVersion)
This isn't correct, as I get a nothing displayed for the value part. The label appears, but no version number. What am I doing wrong?
Edit: Changing the
#Html.DisplayText(Model.ServiceVersion)
, to just
#Model.ServiceVersion
has fixed it. Is this the right way to do this?

either you can try what #karthik has mentioned in the comments or you can use the attribute
[ReadOnly(true)]
[DisplayName("Service Version")]
public string ServiceVersion { get; set; }
and in the view use the default
#Html.LabelFor(m=>m.ServiceVersion) #Html.DisplayText(Model.ServiceVersion)

Related

How to change the text returned by DisplayFor in Razor Pages?

In MVC, I used a DescriptionAttribute to change the text returned by DisplayFor().
But I can't figure out how to do this in Razor Pages.
I tried:
[Description("Available Spots")]
public int? AvailableSpots {get; set; }
And I tried:
builder.Entity<Location>()
.Property(m => m.AvailableSpots)
.HasComment("Available Spots");
And still my column headers display as AvailableSpots.
It's frustrating how Core has taken away so many conveniences we had before. Does anyone know how to change the text returned by DisplayFor()?
[Display(Name = "Available Spots")]
public int? AvailableSpots {get; set; }

ASP.net MVC Is it possible to modify a class object in a view?

I am a newbie and creating a website where you can create your own custom quizes. Ive made a database that stores a class object mytests that consists of a name, and a list of questions parameter.
public class MyTests
{
public int ID { get; set; }
public string name { get; set; }
public string description { get; set; }
public List<MyQuestions> AllTestQuestions;
}
//using this object for questions
public class MyQuestions
{
public string QuestionDescription { get; set; }
public string MultipleChoiceCorrect { get; set; }
public string MultipleChoiceB { get; set; }
public string MultipleChoiceC { get; set; }
public string MultipleChoiceD { get; set; }
public string Answerexplanation { get; set; }
}
I'm using the default database code generated by visual studio. I have no problem adding this test object(mytest) to the database, but what I want to do is that on the edit.cshtml view I want to be able to add elements to the question list before returning the object to the database saved.
The problem is I don't know how to edit the model object from the view, or if this is even possible. I could maybe get it to work through a redirect? but I thought that adding the elements directly from the view would be easier. Is it possible to modify the model.object inside a view from the view (putting security concerns aside)?
For example model.title = something;
or
model.list.add()
Is anything like this possible?
If this question is not clear please let me know and I will try to clarify in the comments.
Yes, it is possible to edit the model from within the view.
From within your .cshtml file specify the view model using the #model declaration, then edit the model like so:
#model Namespace.For.MyTests
#Model.name = "Hello World";
<p>#Model.name</p>
Whilst this would work, it's not really what the view is for so I wouldn't recommend it.
The view is about presenting your data, not mutating it - that should be done in the controller, or domain layer. As soon as the user leaves the page then your changes will be lost due to the stateless nature of the web (.NET MVC passes data to the view from the controller, then ends the request).
This should be done at the controller level. You could do it on a view but it's not what the view is for.
Your issue is that if the page is refreshed you will lose you content, so if you do anticipate on the page refreshing you will need a way in which to temporarily hold the information before it being saved.
On a side note, I'd also consider renaming your classes "MyTests" to "MyTest" (singular) and "MyQuestions" to "MyQuestion"... it's just good practice because then you'd have a List of singleton "MyQuestion" in a "MyTest". EntityFramework Codefirst will pluralise the names when the database is created/update.

What's the syntax for Html.Display()?

I've got a model like this:
public class HomeViewModel
{
public IEnumerable<NewsItem> NewsItems { get; set; }
public decimal TotalSales { get; set; }
public IEnumerable<SalesOrderHeader> SalesInformation { get; set; }
}
And in the View I want to do this:
<p>#Html.Display(Model.TotalSales)</p>
But I'm running into this error:
HomeViewModel does not contain a definition for Display"
Which is odd because it should be the Html type that has Display.
What is the correct syntax for what I'm trying to achieve?
It's better to use DisplayFor (Display) fo doing this. If you need to add some display attributes (like only last 2 digits to be shown) you will do this only one time in the ViewModel.
<p>#Html.DisplayFor(model => model.TotalSales)</p>
If you really want to use Display, the MVC is smart enough to render this with your data from Model.
<p>#Html.Display("TotalSales")</p>
Okay it's actually:
<p>#Model.TotalSales</p>
Solved!

Using the collection's DisplayName from within DisplayTemplate for a single element

To begin with, the code we have no problems with. It's a model:
[DisplayName("A very hot hotshot")]
public Person Hotshot { get; set; }
[DisplayName("Just a developer")]
public Person Developer { get; set; }
[DisplayName("Some random guy")]
public Person RandomGuy { get; set; }
And then we have a view which looks like this:
#Html.DisplayFor(m=>m.Hotshot)
#Html.DisplayFor(m=>m.Developer)
#Html.DisplayFor(m=>m.RandomGuy)
DisplayTemplate for Person has a line which uses model's DisplayName:
#Html.DisplayNameForModel()
It's all nice, but the problem appears when you add a list property to the model and try to display it with DisplayFor. Here's the model part:
[DisplayName("Funny guys")]
public IEnumerable<Person> FunnyGuys { get; set; }
And, as DisplayFor is capable of displaying IEnumerable<T> iterating the T template, I'm calling it just like for other properties:
#Html.DisplayFor(m=>m.FunnyGuys)
It works great, except for fetching that DisplayName from the containing collection. It's set to null, since the attribute is on IEnumerable property, and the template gets a single element from it.
I had to use the workaround:
#Html.DisplayFor(m=>m.FunnyGuys, new {CollectionDisplayName = "Funny guys"})
And then using that property if DisplayName is null in Person template.
Is there a cleaner way?
I suppose DisplayNameFor helper is what are you looking for:
#Html.DisplayNameFor(m => m.FunnyGuys)
Also it's better to use Display attribute over DisplayName becose it's come from System.ComponentModel.DataAnnotations namespace and you can use not only literals in it but also resorses in your project. In case is you will localize your application.
[Display(Name = "Funny guys")]

Problem getting the MVC3 model binder to bind to a decimal instead of an int

I have a AJAX call from my webpage sending the following data to my MVC3 action method.
{
"name":"Test",
"newitems":[
{"id":15,"amount":100,"unit":"gram"},
{"id":1,"amount":75,"unit":"gram"},
{"id":46,"amount":25,"unit":"gram"}
]
}
In my controller I have the following classes:
public class NewDataItem
{
public string name { get; set; }
public List<NewDataItemDetails> newitems { get; set; }
}
public class NewDataItemDetails
{
public int id { get; set; }
public int amount { get; set; }
public string unit { get; set; }
}
And the Action method that received the request have a NewDataItem as a parameter. This works perfect, however the amount property of NewDataItemDetails might not always contain an int. It might for example be 50.45. So because of that I changed the line public int amount { get; set; } to public decimal amount { get; set; }.
After this change amount is always shown as 0, and not the proper value that it did when it was an int.
Why does MVC fail to bind the value to the property when it is a decimal, when it worked just fine as an int?
See the answer here Default ASP.NET MVC 3 model binder doesn't bind decimal properties from ryudice about creating a DecimalModelBinder. It works and it also keeps all the model validation working, (some other solutions use deserialization which can stop validation from working.
I found the problem.
If I change the line "amount":100, to "amount":"100", it works fine. It seems that the MVC ModelBinder can manage the string to decimal conversion, but not the int to decimal.
Your type (class) NewDataItemDetails property amount is of type int.
You are making things difficult to manage. If you are expecting to have amount as a decimal eventually, it simplifies to actually use amount's type as decimal.
This will avoid having you to extend the default model binder and cater for your behaviour.
I think, it is wiser and it simplies to send the amount as decimal in the ajax call. it provides consistency.
I know I am a bit late with this but there is another solution which works without changing anything until MVC fixes it (I believe it is at their end).
In my javascript I add 0.00001 to my value if it is supposed to be a decimal but is a round number. For those I know should be currency values I know this has no effect and will round down. For those that I do not know their value and this could affect it I remove the 0.00001 from the value after binding in mvc. The binding works correctly as this is no longer an int in the eyes of mvc
If you don't want to change model binder then you can create json object and convert amount to string.It will work fine for me.
var test={"amount":""};
var test1={"amount":100}
test.amount=test1.amount.toString();

Categories