I have a table called TestAnswer and one called question
This is the Create Script created by Entity Framework. I have added some viewbags
ViewBag.TestAnswerQuestion gives me values from the Question table as a select list. I want to show them as normal text e.g. #Html.DisplayFor(model => model.QuestionText) in my razor view for TestAnswer
How can i get the questions to show in my TestAnswer create view
// GET: /TestAnswer/Create
public ActionResult Create()
{
ViewBag.CurrentTestUser = User.Identity.Name;
ViewBag.CurrentTestUserId = User.Identity.GetUserId();
**ViewBag.TestAnswerQuestion = new SelectList(db.Questions.Where(t => t.QuestionID == 2), "QuestionID", "QuestionText");**
ViewBag.TestAnswerTestID = new SelectList(db.Tests, "TestID", "TestUser");
return View();
}
Looks like you need to pass a Model back to your View when returning from your Controller action method.
If I understand you correctly, you want to return a Question entity to your TestAnswer/Create view, perhaps something like:
var model = db.Questions.Find(t.QuestionID);
...
return View(model);
Then you can reference the model from the View template:
#Html.DisplayFor(model => model.QuestionText)
If you want to show a select list of Answers to the Question, your Question entity could have a collection of Answer entities as a public property, then you can simply navigate from a Question to its Answers.
The best advise I can give you is to consider the Entities and their relationships carefully, and model them as POCO classes. Depending on what you are trying to achieve, you may want tot return a View Model, when is a transformation of you entity model to another form that is optimized for the View.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have a table in my SQL database, and using MVC on a ASP.NET Core:
CREATE TABLE [dbo].[ProgramVersion] (
[ID] INT IDENTITY (1, 1) NOT NULL,
[Ver] VARCHAR (10) NOT NULL,
[Released] DATETIME NOT NULL
);
Very simple. I have a scaffolded Edit.cshtml file, has a form for editing a records from a different table. I just want to use the records in the ProgramVersion table to populate an HTML select input (i.e. drop down list).
How do I execute a simple query that gives me a result-set?
How do I iterate through the result-set and simply put the 'Ver' string value into the Options tags in the drop-down list?
(In PHP, this is dead simple, but C# is really frustrating me.)
First you create a view model which can transfer data between your action method and view. Add 2 properties to this, one for passing the list of options needed and one for holding the selected option value
public class CreateVm
{
public List<SelectListItem> Items { set;get;}
public int SelectedItemId { set;get;}
}
Now in your GET action, create an object of this, load the Items properties and pass it to the view
public ActionResult Create()
{
var vm = new CreateVm();
//Load the Items property by reading the ProgramVersion table data
vm.Items = db.ProgramVersions
.Select(x=>new SelectListItem { Value=x.Id.ToString(),
Text=x.Ver} )
.ToList();
return View(vm);
}
Now in your view, which is strongly typed to this view model, you can use the DropDownListFor hepler method
#model CreateVm
#using(Html.BeginForm())
{
#Html.DropDownListFor(s=>s.SelectedItemId,Model.Items,"Select one")
<input type="submit" />
}
You can use the same view model in your HttpPost action method as a parameter
[HttpPost]
public ActionResult Create(CreatVm model)
{
// check model.SelectedItemId
// to do : return something
}
I have a two questions.
The first one is about that moment when you go to EDM and update your models from database and it rewrites the old models, losing everything you edited inside them. I read a little about this and it is said that you can create another models and make them also partial and there you may put again the fields so at the next update it won't affect your last changes. How can I do this? I have a separate project for my DAL and the models were generated from database (I have an EDM).
The second question is... But better I give an example. I have a model called Categories and another one CategoriesTranslations, both of them mapped from my database. Let's say you want to have a list of this categories inside a DropDownList() in many views of your website (of your different controllers). The DropDrown will have the value containing the translation which depends on the current language and the keys containing the category ID.
Here is an example of my list:
List<SelectListItem> listItems = new List<SelectListItem>();
var CategoriesTexts = db.Categories.Include(i => i.CategoryTexts).ToList();
foreach (var cat in CategoriesTexts)
{
var texts = cat.CategoryTexts.Where(w=>w.Language.Format == (string)Session["chosen_language"]).FirstOrDefault();
listItems.Add(new SelectListItem
{
Text = texts == null ? cat.Id.ToString() : texts.Name,
Value = cat.Id.ToString(),
});
}
Where should I put this code in my website structure (or how can I structure it) to make use of it in most of my Views?
Thank you!
For your first question
There is no need to make partial classes just to fix the naming when you update EF EDMX file. Actually you shouldn't delete the model class from the Edmx when you make update to your database all you need to do is to update the model and it will save your navigation properties names as you made them already.
For your second Question
Although I don't agree with you about what you're doing to get the categories to the DropDownList, But you could make this as Extension method for the IEnumerable<Category> and put this method in ViewModelExtensions project
e.g.
public static IList<SelectListItem> ToDropDownList(this IEnumerable<Category> query)
{
List<SelectListItem> listItems = new List<SelectListItem>();
foreach (var cat in query)
{
var texts = cat.CategoryTexts.Where(w=>w.Language.Format == (string)Session["chosen_language"]).FirstOrDefault();
listItems.Add(new SelectListItem
{
Text = texts == null ? cat.Id.ToString() : texts.Name,
Value = cat.Id.ToString(),
});
}
}
then just call it in your controllers like this:
var list = db.Categories.Include(i => i.CategoryTexts).ToDropDownList();
I currently have a model that is passing a dogs variable into the view:
public ActionResult Summary()
{
var dogs = repository.GetAllRecords().OrderByDescending(x => x.DateRecieved);
return View("Summary", dogs);
}
This has a field in it called OutcomeID, which references another array by ID:
var categories = new List<Category>();
try
{
this.Connect();
var cmd = new SqlCommand
{
CommandText = "dbo.GetSummaryOutcomes",
CommandType = CommandType.StoredProcedure,
Connection = this.cn
};
var result = cmd.ExecuteReader();
while (result.Read())
{
categories.Add(new Category
{
Name = result["Outcome"].ToString(),
Value = result["id"].ToString(),
InUse = bool.Parse(result["InUse"].ToString())
});
}
}
Is there anyway so that on my view I can combine these, and instead of just having the OutcomeID, I reference the Outcome result from the categories list?
ie I need to get result["Outcome"] based on matching dogs.OutcomeID to result["id"]
Sorry if this sounds like a silly question, in PHP this wouldn't be a problem for me, but I'm very new to ASP.NET MVC and I'm not sure where to begin
Thank you
You can create a View Model which is a common practice in ASP.NET MVC, basically you will have to create a new class with the properties that you need to pass on to your view, then in your controller you will send the instace of the view model to your view and also transform your data into the viewmodel.
Have a look here ASP.NET MVC - How exactly to use View Models. Also you might want to have a look at automapper, which is a mapping library that removes a lot of the boilerplate code involved when working with view models.
I just started to learn MVC3. Have been coding in traditional ASP.NET For a while and now would like to move to MVC.
Some things that i don't understand (probably just been used differently then in traditional ASP.NET)
I'm trying to write a simple news module that will display news and allow to insert comment for them.
So first step is, i created a tables on my SQL server:
TblNews
TblCategories
TblComments
Created Linq2SQL data Class in Models folder and named it News.dbml
Created Controller HomeController.cs and a method called Index() in it.
Look like this:
public ActionResult Index()
{
Models.NewsDataContext db = new Models.NewsDataContext();
var Model = (from n in db.TblNews
select new
{
ID = n.ID,
Title = n.Title,
Description = n.Description,
Category = n.TblCategory.CategoryName
});
return View(Model);
}
As you see I'm trying to select all the news and their category names (TblNews and TblCategories do have relationship between them)
After that I'm returning the data that i got from the query.
In the View i have:
#{
ViewBag.Title = "News Index Page";
}
<table>
#foreach (var item in Model)
{
<tr>
<td>
ID: #item.ID<br />
Title: #item.Title<br />
Description: #item.Description<br />
Category: #item.Category
</td>
</tr>
}
</table>
Which should return something like:
ID: 4
Title: asd
Description: asd
Category: 2
That's my sample data from tables.
When i run the page it gives me error message:
'object' does not contain a definition for 'ID'
but when i focus my mouse on "item" variable it actually contain:
{ ID = 4, Title = asd, Description = asd, Category = Test2 }
I also tried to return Linq Query as list by adding .ToList() to the end of it.
Can anybody give me any hints and get me into the right direction?
Sorry if i explained something incorrectly. English is not my primary language.
Please ask if you need any more information.
Thank you very much.
P.S. I'm using Visual Studio 2012
You're missing your model declaration at the top of your view so will default to type object. When you do item.ID you're doing object.ID, which is why it complains that object does not contain a definition for ID
Add the following:
#model List<Models.NewsDataContext>
Also, make sure you evaluate the LINQ query by calling .ToList() before your return Model, that way the query is already executed against the database before it hits the view:
return View(Model.ToList());
Edit: Actually, in your LINQ query you are selecting into an anonymous type, you must use a concrete class in order to use this in your view. The below assumes your TblNews corresponds to a class called News:
var Model = (from n in db.TblNews
select new News //class name here
{
ID = n.ID,
Title = n.Title,
Description = n.Description,
Category = n.TblCategory.CategoryName
});
return View(Model.ToList());
Then change your model to:
#model List<News>
forgive me as I am fairly new to using ASP.net MVC 3...
I have two tables - one called Contract, one called Sow. Contract has a foreign key that points to SOW. What I'd like to do is to be able to edit the Contract details and provide a drop down list of different SOW records to choose from. The current code:
In my Contract Controller:
public ActionResult Edit(int id)
{
Contract contract = contractRepository.GetContract(id);
var db = new ManagementDataContext();
IEnumerable<SelectListItem> items = db.Sows
.Select(s => new SelectListItem()
{
Value = s.ID.ToString(),
Text = s.Title
});
ViewData["Sow"] = items;
return View(contract);
}
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
Contract contract = contractRepository.GetContract(id);
try
{
UpdateModel(contract);
contractRepository.Save();
return RedirectToAction("Details", new {id = contract.contractID});
}
catch
{
ModelState.AddRuleViolations(contract.GetRuleViolations());
var db = new ManagementDataContext();
IEnumerable<SelectListItem> items = db.Sows
.Select(s => new SelectListItem()
{
Value = s.ID.ToString(),
Text = s.Title
});
ViewData["Sow"] = items;
return View();
}
}
In my Edit.aspx:
<%: Html.DropDownList("Sow") %>
The list populates with values, but when I change them and update, the foreign key does not change. Any advice or help? Also, if you want to throw in a way I could improve my current code?
Again, I apologize for my lack of ASP.net knowledge, but you gotta get your hands dirty and make mistakes in order to learn.
This is going to generate a select with name="Sow".
What you want is the input to have the same name as the FK property you want to bind it too.
Probably something like <%: Html.DropDownList("SowId") %>
Firstly, I highly recommend you to use ViewModel pattern with AutoMapper.
Whatever, in you scenario, should work if you do something like
public ActionResult Edit(int id)
{
Contract contract = contractRepository.GetContract(id);
var db = new ManagementDataContext();
IEnumerable<SelectListItem> items = db.Sows
.Select(s => new SelectListItem()
{
Value = s.ID.ToString(),
Text = s.Title
});
ViewData["SowItems"] = items;
return View(contract);
}
Your view:
<%: Html.DropDownList("SowId", ViewData["SowItems"]) %>
the possible problem can be with ModelState and I can't right now give to you a clear explanation.
hope it help you
A few approaches for you to try mixed with some code help.
1st: change your [HttpPost] Edit method to accept a Contract parameter instead of FormCollection, its much cleaner
[HttpPost]
public ActionResult Edit(Contract contract)
As long as the fields of Contract are the names of your input fields, then you are set as the MVC toolkit will map them to a Contract object that is then passed to your Action method.
This will also allow you to take advantage of Unobtrusive Validation, meaning MVC framework will validate the data inputs to your model object before it gets to your Action method. You will still have to perform Business Rule validations or Data Model Relational validations, but it helps.
2nd: I prefer to create SelectLists in the View (probably get killed over this), but I think SelectList is definitely a View abstraction of your data which has nothing to do with Control or Model, here's a way to do it, and here's where a ViewModel comes in handy
[Side note here for ViewModel, it helps get away from using Strings to pull things out as Objects from ViewData, which in some cases (like SelectLists) need to then be cast in order to compile]
Controller code
var model = new ContractViewModel()
{
Contract = contractRepository.GetContract(id),
Sows = db.Sows.ToList() // ToList() is important here to ensure the data is pulled into the Model
}
// Do any other initializations here
ViewData.Model = model;
return View();
View code
<%= Html.DropDownListFor(model => model.Contract.Sow, new SelectList(Model.Sows, "ID", "Title")) %>
An alternative, if either this won't work for you or you need different validations is:
Controller code
[HttpPost]
public ActionResult Edit(Contract contract, int sowID)
View code
<%= Html.DropDownList("sowID", new SelectList(Model.Sows, "ID", "Title")) %>
Hope this helps.