How to show data from two different tables in one 1 view - asp.net-mvc

I'm creating a forum where user can ask questions and comment on it ....using mvc3
Inside that i have a link "details" for each question .... in side that i have 2 more links "show" and "add comments"
in show one can see all comments related to a particular Question
and in Add comments we can add a comment for particular question
its controller code is as follow:
public ActionResult Addnew(int id)
{
return View();
}
[HttpPost]
public ActionResult Addnew(Answer answr, int id)
{
answr.QuestionQId = id;
_db.Answers.Add(answr);
_db.SaveChanges();
return RedirectToAction("Index");
}
and in view i have written:
#model Hobby.Models.Answer
#{
ViewBag.Title = "Addnew";
}
<h2>Addnew</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Answer</legend>
<div class="display-label">Question</div>
<div class="display-field">
#Html.DisplayFor(model => model.Question.Que)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Ans)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Ans)
#Html.ValidationMessageFor(model => model.Ans)
</div>
<p>
<input type="submit" value="Add Comment" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
but it is not showing the Question from question table.....
Please help me

I don't see where you are binding the necessary data I think AddNew [Get] method should get the question from DB and set it to the view, I suppose you should do something similar to this
public ActionResult Addnew(int id)
{
Answer ans = new Answer();
ans.Question = _db.Questions.SingleOrDefault(q => q.Id == id);
return View(ans);
}

#Jayanga is right but I think you still wanted to show data from "2 tables" as you stated in the title of your question. Assuming you mean that you want to show the question and all related answers, and also assuming that this is .NET Entity Framework (don't know by heart the syntax of Linq2Sql), you would do:
public ActionResult Addnew(int id)
{
var question = _db.Questions.Include("Answers").SingleOrDefault(q => q.Id == id);
return View(question);
}
This changes your binding model type to Question, but I'm assuming here that a Question can have more than 1 answer, and in that case, you'll have in your View all the information you need... something like this:
// In your .cshtml file
<article class="question">#Model.Que</article> #* this is your question text *#
#foreach (var answer in Model.Answers.OrderBy(a => a.PostedDate)) { #* assuming you want to sort this *#
<article class="answer">#answer.Ans</article> #* this would be your answer text *#
}

Related

Passing data from a View to a Controller in .NET MVC - "#model" not highlighting

The following code works as I need it to:
#using (Html.BeginForm("LOLOL", "PATIENT", null))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>PATIENT</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</fieldset>
<p>
<input type="submit" value="SUBMIT" />
</p>
}
In LOLOLController:
[HttpPost]
public IActionResult LOLOL(Patient p) {
var client = new MongoClient("mongodb://localhost:27017");
var userId = _userManager.GetUserId(HttpContext.User);
string db_name = "test" + userId;
var database = client.GetDatabase(db_name);
var collection = database.GetCollection<BsonDocument>("patients");
var filter = Builders<BsonDocument>.Filter.Eq("Name", p.Name.ToString());
var document = collection.Find(filter).First();
// I'm cutting short the rest of the code, because when I do something
// similar later, "collection.Find(filter).First()" fires an exception, I'll
// explain..
return View(p);
}
I have something equivalent to taking off the fieldset element in the HTML, leaving basically just a button in the "Html.BeginForm", but then the data is clearly not binding properly, which I know because if I just have a button and no data-entry, I click the button and then I get an error saying the data cannot be found from the database. (EDIT: I now have confirmed that this is indeed because the Patient object is not being passed to the controller quite as I expected it to, seems like a brand new Patient object was created upon calling html.beginform ... I thought that maybe the old Patient object was being passed so I did not have to enter all its data members every time we use Html.BeginForm)
In sum, I want to fill out a text box, click a button to load a new page and display the value of that textbox, but have that value also persisted in essentially a session state, so that if I call another Html.BeginForm function and go into a third view, the text from the first view will be displayed in the third view, even though I did not have to type its value in the second view. Hopefully I can repeat this process, and essentially load up the data members of a class with one view per data member.
Make sure you pass the data from the previous view to the new view from your Controller. When you pass it, include #HiddenFor for those properties from the previous view in your new view. That way the new view will keep and then pass the values to your next POST.
#Html.HiddenFor(model => model.PropertyYouPassedAndWantToKeepAndPassAgain
Edit: Here's the logic for using multiple views for one object... as requested.
Model:
public class Patient
{
string Name { get; set; }
string Address { get; set; }
string City { get; set; }
}
Page1 GET:
[HttpGet]
public ActionResult Page1()
{
Patient patient = new Patient();
return View("~/Views/Page1.cshtml", patient);
}
Page 1 View... only ask for the name.
#model mysite.Models.Patient
#using (Html.BeginForm("LOLOL", "PATIENT", null))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>PATIENT</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</fieldset>
<p>
<input type="submit" value="SUBMIT" />
</p>
}
Page1 POST... get the patient and pass it on to the next view...
[HttpPost]
public ActionResult Page1(Patient patient)
{
if (ModelState.IsValid)
{
return View("~/Views/Page2.cshtml", patient); // pass your patient to the second page view with the name
}
else
{
return View("~/Views/Page1.cshtml", patient);
}
}
Page2 GET... get the patient from the prior Page1 POST and send it off to the Page2 View.
[HttpGet]
public ActionResult Page2(Patient patient)
{
// Receive patient from Page1 post and pass it to new view... includes the name
return View("~/Views/Page2.cshtml", patient);
}
Page2 View gets the object... use a HiddenFor to keep the name which you just sent from the GET.
#model mysite.Models.Patient
#using (Html.BeginForm("LOLOL", "PATIENT", null))
{
#Html.HiddenFor(model => model.Name) #* This will keep the name on your next post *#
#Html.ValidationSummary(true)
<fieldset>
<legend>PATIENT</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Address)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Address)
#Html.ValidationMessageFor(model => model.Address)
</div>
</fieldset>
<p>
<input type="submit" value="SUBMIT" />
</p>
}
Since the HiddenFor holds the Name, it will be passed on your next post. It is there but hidden from the form itself.
[HttpPost]
public ActionResult Page2(Patient patient)
{
// Because of the HiddenFor, the Name will be passed because it was kept in the view... but hidden from the form itself.
// It's basically storing it for you to pass again
if (ModelState.IsValid)
{
// Pass object with Name and Address to next controller
return View("~/Views/Page3.cshtml", patient);
}
else
{
return View("~/Views/Page2.cshtml", patient);
}
}
Page2 POST
[HttpPost]
public ActionResult Page2(Patient patient)
{
// Because of the HiddenFor, the Name will be passed because it was kept in the view... but hidden from the form itself.
// It's basically storing it for you to pass again
if (ModelState.IsValid)
{
// Pass object with Name and Address to next controller
return View("~/Views/Page3.cshtml", patient);
}
else
{
return View("~/Views/Page2.cshtml", patient);
}
}
Page3 GET
[HttpGet]
public ActionResult Page3(Patient patient)
{
// Pass patient again... to your next view
return View("~/Views/Page3.cshtml", patient);
}
Page3 View...
#using (Html.BeginForm("LOLOL", "PATIENT", null))
{
#Html.HiddenFor(model => model.Name) #* Keep name again for your next post *#
#Html.HiddenFor(model => model.Address) #* Now we are keeping the address as well *#
#Html.ValidationSummary(true)
<fieldset>
<legend>PATIENT</legend>
<div class="editor-label">
#Html.LabelFor(model => model.City)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.City)
#Html.ValidationMessageFor(model => model.City)
</div>
</fieldset>
<p>
<input type="submit" value="SUBMIT" />
</p>
}
And so on and so forth... until you have your model complete and want to do something with it.

ASP.net MVC - how does controller action method gets parameter value?

I know the title of this question isn't very pretty. I dint have a better way to put it.
Lets look at the following code :
View for delete action:
#model LearningMVC.Models.Blog
#{
ViewBag.Title = "Delete";
}
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<fieldset>
<legend>Blog</legend>
<div class="display-label">
#Html.DisplayNameFor(model => model.URL)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.URL)
</div>
</fieldset>
#using (Html.BeginForm()) {
<p>
<input type="submit" value="Delete" /> |
#Html.ActionLink("Back to List", "Index")
</p>
}
Controller action for delete action
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
Blog blog = db.Blogs.Find(id);
db.Blogs.Remove(blog);
db.SaveChanges();
return RedirectToAction("Index");
}
My questions is, How on earth this method got its parameter ?!

Getting message “Store update, insert, or delete statement affected an unexpected number of rows (0)” ?

Another big problem, here.
I have the model:
public class Lead
{
[System.ComponentModel.DataAnnotations.Column("le_codlead")]
public int LeadID {get; set; }
[System.ComponentModel.DataAnnotations.Column("le_descr1")]
[Required(ErrorMessage="Inserire Nome del Lead")]
[Display(Name="Nominativo Lead")]
public string Name1 {get; set;}
[System.ComponentModel.DataAnnotations.Column("le_descr2")]
[Display(Name = "Nominativo secondario")]
public string Name2 { get; set; }
...
...
...
}
Controller (for the Create Method):
[HttpPost]
public ActionResult Create(Lead lead)
{
if (ModelState.IsValid)
{
db.Leads.Add(lead);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(lead);
}
and this is the View:
#model CRMArcadia.Models.Lead
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true, "ATTENZIONE! Compilare tutti i campi obbligatori")
<fieldset>
<legend>Lead</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name1)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name1)
#Html.ValidationMessageFor(model => model.Name1)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Name2)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name2)
#Html.ValidationMessageFor(model => model.Name2)
</div>
...
...
...
<p>
<input type="submit" value="Create" />
</p>
</fieldset> }
But when I try to insert a new Lead it throws the exception as in the Post Title: Entity Framework: “Store update, insert, or delete statement affected an unexpected number of rows (0).” I read on the web it is caused by the ID key (LeadID, in this case) not updating: they suggest to insert an hiddenfor attribute in the view for the ID key, and so I did:
#Html.HiddenFor(model => model.LeadID)
But with this one at the pressure of the Create button nothing happens.
Does someone has a solution (or a workaround ;) ) at this problem, please?
Thanks.
Do you have some extra layer to communicate with EF ? what is your entity context?
For Update scenario:
If you are using same action for Create/Edit then just place your #Html.HiddenFor(model => model.LeadID) - hidden field between blocks #using (Html.BeginForm()) { .... </fieldset> }.
If it does not help, look at this article MSDN - Working with Objects

RedirectToAction / CanvasRedirectToAction Giving 404 Error Because Virtual Directory Name is Repeated in URL

I am just getting started with ASP.Net MVC 3 with the Facebook C# SDK. I've had pretty good luck so far, but I am having an issue when returning RedirectToAction or CanvasRedirectToAction in a Controller method.
When I click either the Submit or Create New_ button in the view below, I always get send to
/app/app/Event/Create instead of app/Event/Create, resulting in a 404
Thanks in advance!
EventController:
[CanvasAuthorize(Permissions = "user_about_me,user_events,create_event")]
public ActionResult Index()
{
return View();
}
[CanvasAuthorize(Permissions = "user_about_me,user_events,create_event")]
public ActionResult Create()
{
return View();
}
[CanvasAuthorize(Permissions = "user_about_me,user_events,create_event")]
public ActionResult Persist()
{
return this.CanvasRedirectToAction("Index", "Event");
}
Event/Create.cshtml
#using Facebook.Web.Mvc
#model App.Models.Event
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"> </script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm("Persist", "Event")) {
#Html.FacebookSignedRequest();
#Html.ValidationSummary(true)
<fieldset>
<legend>Event</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" value="Create" />
#Html.CanvasActionLink("Create New", "Persist")
</p>
</fieldset>
}
It doesn't appear like it's easily possible. My guess is that the javascript that looks at the URL in the frame within the C# SDK doesn't do a good job of creating the correct path to redirect to. I just got rid of the virtual directory to solve the problem for now.

keeping Object Data after passing it to a strongly typed view

I have a simple ASP.NET MVC 3 site, from my Controller out of the Edit Action I pass a Object (a class which is also mapped by nhibernate)
After editing and clicking save i pass it to the [HTTPPost] decoraded Method but and all properties are correct, excerpt the "id" property it hat a guid value equivalent to NULL (00000000-0000-000...).
Is there a problem using the Domain Model to strongly type my Views? May the problem be that Id has:
{get; private set;}
???
Thanks in advance.
Here The Code:
My View:
'#model fnh.DataModel.Kunde
#{
View.Title = "EditKunde";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>EditKunde</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Fields</legend>
#Html.EditorFor(model => model._id)
#Html.EditorFor(model => model._KdNr);
<div class="editor-label">
#Html.LabelFor(model => model._Name)
`enter code here` </div>
<div class="editor-field">
#Html.EditorFor(model => model._Name)
#Html.ValidationMessageFor(model => model._Name)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
'
My Controller Actions:
' public ActionResult EditKunde(Guid id)
{
return View(_kunden.GetKundeById(id));
}
[HttpPost]
public ActionResult EditKunde(Kunde kunde)
{
Ansprechpartner anp = new Ansprechpartner();
anp._Name = "JustATry";
kunde._Ansprechpartner.Add(anp);
`enter code here` _kunden.EditKunde(kunde);
return View();
}'
Are you adding the Id property to your form (maybe as a hidden field)?
It would be useful if you post the Action code (for both Edit Actions), and the View.

Resources