If I understand the [ScaffoldColumn(false)] attribute correctly, I should be able to decorate a variable with this and then, when I create a strongly-typed Edit view, that field will show up as hidden text and NOT a Label/Textbox pair.
I am using entity framework and then adding a partial class with an inner metadata class like so:
[MetadataType(typeof(AlumniInterest_Metadata))]
public partial class AlumniInterest
{
private class AlumniInterest_Metadata
{
[ScaffoldColumn(false)]
[DisplayName("Person Id")]
[StringLength(8)]
public object person_id { get; set; }
[DisplayName("Interest")]
[StringLength(35)]
public string interest_desc { get; set; }
}
}
This partial is in the same namespace as the EF generated class and the DisplayName attribute IS being picked up so I think things are wired correctly. I tried changing the type from string to object (based on some google search results) but that did nothing.
Anyone else run into this problem? Have I made a newb error?
The MVC tooling does not reason about ScaffoldColumnAttribute. This attribute is only used when you invoke the Html.DisplayForModel or Html.EditorForModel methods.
If you wanted the Add View dialog to honor ScaffoldColumnAttribute you could edit the T4 template file that's used to generate a View.
The [ScaffoldColumn(false)] does not seem to work as you would expected. You will need to set
Html.HiddenFor(model => model.person_id)
in your view manually.
Related
In TagHelpers we usually have a property called asp-for to connect the TagHelper to a Model property.
I created a custom TagHelper, and added a property like a asp-for:
[HtmlTargetElement("myinput", TagStructure = TagStructure.WithoutEndTag)]
public class MyInputTagHelper : TagHelper {
public ModelExpression Field { get; set; }
}
Normally, if the bound model is a complex type with subclasses and I need the full path to that property, I can get the full access path by evaluating System.Linq.Expressions.Expression. How can I achive this with ModelExpression?
I Have a model:
public class PersonVM
{
public Person Person { get; set; }
}
and in .cshtml:
#model PersonVM
<myinput field="Person.PersonAddress.City"/>
In the TagHelper MyInputTagHelper, I need the full request path. In this example it would be "Person.PersonAddress.City". All I could get is "City" via Field.Metadata.PropertyName.
Ok I got it, the original expression is saved in
ModelExpression.Name
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.
In a ASP.NET MVC 5 web site I have a GridView using the devexpress component binding using the LINQ method.
EF generated a partial class to map a table that i use to display in that gridview.
In this partial class generated by the EF i have a ID_Status property wich has a corresponding description in other table. I made another partial class to deal with this custom Property and it works ok, except when i try to make a 'Sort' operation clicking on the header of this column.
The partial class generated by the EF.
[Table("Test")]
public partial class Test
{
[Key]
public long ID_Test { get; set; }
public long ID_TestStatus { get; set; }
//other properties
}
My Custom partial class:
public partial class Test
{
private static readonly TestRepository _testRepository;
static TestRepository()
{
_testRepository= new TestRepository();
}
public string StatusDescription
{
get { return _testRepository.GetStatusDescriptionById(ID_TestStatus); }
}
}
When i try to Sort using another column it works fine, but when i try to Sort using the custom property Column all the grid cell values gets empty, without any value.
Any suggestion?
It's not a very good idea to have data access code inside an entity. One reason is that it makes it very hard to write unit test. Another reason is that it is very likely to give rise to the n + 1 anti pattern. In your case, it does: one (1) query to get the Tests, then each Test (n) sends a separate query to the database to get its StatusDescription.
The way you implemented it also raises some eyebrows, because
_testRepository is static, which meas there is probable some context instance living for the entire lifecycle of the application - unless GetStatusDescriptionById creates a new context for each call, but that wouldn't be a good idea either.
The GetStatusDescriptionById call is made each time the property is accessed. In a web application this may not be a big problem because the objects are newly created each time they are requested anyway, but in other environments this could be highly inefficient.
A better approach would be to fetch the Testss with their Status included:
context.Tests.Include(t => t.TestStatus)
and have an unmapped property like
public string StatusDescription
{
get { return TestStatus== null ? string.Empty : TestStatus.Description; }
}
better still (in my opinion) would be not to show Test objects directly, but TestDto objects like
public class TestDto
{
public string StatusDescription { get; set; }
//other properties that match Test's properties
}
and use a tool like AutoMapper to map a collection of Tests to TestDtos. If Test has a property Status and TestStatus has a property Description, AutoMapper will be able to flatten that into StatusDescription automatically.
Both this StatusDescription property and the Dto appraoch set the state of a Test(Dto) object once. I don't think any grid component can mess with that.
I am starting a new MVC project and it is definetly known that each view required the next items: user language, timezone and few user settings referred to city, country, etc. So, I am going to make some base entity where to put this properties. But some view would be type of PagedList (class from opensource MvcPaging library). And I am not sure how to combine Base model and PagedList in one object?
I thank about interfaces but I read that it is more complex rather then using classes.
sounds like you should look into inheritance:
public class BaseModel
{
public string UserLanguage { get; set; }
...
}
public class SomePageModel : BaseModel
{
public int Id { get; set; }
public PagedList<Whatever> PagedStuff { get; set; }
...
}
In this case SomePageModel inherits all properties of BaseModel. You don't need to use PagedList as a Model. You can use SomePageModel as a model for a view, which has inside the PagedList. In this case you'd write in the view:
#model [namespace].SomePageModel
//to access paged stuff:
#Model.PagedStuff
But really your question lucks specifics and it's hard to direct you in the correct direction based on the information you've provided thus far.
I have my ADO entity generated in MVC 2 and I know that if I want to put custom validation on an object I can do something like this.
[MetadataType(typeof(MyEntity_Validation))]
public partial class MyEntity
{
private sealed class MyEntity_Validation
{
[Required]
[RegularExpression("[A-Za-z][0-9]{5}")]
public string SomeField{ get; set; }
}
}
But I don't know why that works.
How does that work? Some sort of convention?
Metadata is a convention, yes. See http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx. You can add attributes to fields to enforce validation, display, concurrency, all sorts of common usefulness. Hope this helps.