I am at very basic stage of asp.net MVC development. So sometimes I struggle with simple LINQ queries to work.
scenario-
I have A page that has some Image and comment on that Image by users (Just Like a post on facebook containing comments from users).
So I am saving those comments from the textarea and sending Image ID via Ajax query.
Here Is my controller action method-
Saving comment-
[HttpPost]
public void SaveComment(CardModel card) {
CardCommentTable commenttable = new CardCommentTable();
commenttable.CardComment = card.cardComment;
commenttable.FKcardID = card.cardID;
db.CardCommentTables.InsertOnSubmit(commenttable);
db.SubmitChanges();
}
This Comment is saved in CardCommentTable that has foreign key reference of Table in that Image is saved.
Rendering Image and other fields on view page-
This query renders Image and other fields that make it An Image post. Like title, dateofsubmit, Like etc.
public ActionResult CardDetails(CardModel card) {
var cardDetail = (from u in db.CardTables
where u.CardID == card.cardID
select new CardModel {
cardID = u.CardID,
cardHashCode = u.CardHashCode,
cardDate = u.CardDate,
cardFileName = u.CardFileName,
cardFilePath = u.CardFilePath,
cardTitle = u.CardTitle
}).ToList();
return View(cardDetail);
}
Now In cardTable I have one more column named cardComment in that I want to show all those saved comments from table CardCommentTable.
So I tried-
public ActionResult CardDetails(CardModel card) {
var allsavedcomments= (from u in db.CardCommentTables
where u.FKcardID == card.cardID
select u).ToList();
var cardDetail = (from u in db.CardTables
where u.CardID == card.cardID
select new CardModel {
cardID = u.CardID,
cardHashCode = u.CardHashCode,
cardDate = u.CardDate,
cardFileName = u.CardFileName,
cardFilePath = u.CardFilePath,
cardTitle = u.CardTitle,
cardComment = allsavedcomments // Trying to render all saved coments here.
}).ToList();
return View(cardDetail);
}
View-
#model IEnumerable<FunRanger.Models.CardModel>
#foreach (var item in Model) {
<script type="text/javascript">
$(function () {
$('#save-comment').click(function () {
var textareavalue = $('#textarea-comment').val();
$.ajax({
url: '/Home/SaveComment/',
type: 'post',
data: '&cardComment=' + textareavalue + '&cardID=' + '#item.cardID',
success: function (data) {
$('#all-comments').append(data);
}
});
});
});
</script>
using (Html.BeginForm()) {
#Html.ValidationSummary(true)
#if (Model != null) {
<h2 class="header-wrapmain">
#item.cardTitle
</h2>
#item.cardDate.ToShortDateString()
<img src="#item.cardFilePath" />
<a href="#" class="#item.cardHashCode" rel="tooltip" data-placement="bottom" title="Filter by #item.cardHashCode">
##item.cardHashCode</a>
}
else {
<div class="alert alert-danger">
No More items to preview
</div>
}
}
<textarea class="span12" rows="5" id="textarea-comment" style="resize: none" placeholder="Enter a comment..."></textarea>
Save comment
<ol>
<li>
#item.cardComment
</li>
</ol>
}
How can I insert List result in a column here.
How do I show all saved comments with this above query?
Thanks for any help.
I slightly renovated your code with Foreign key relations ship. This will save your from using two different queries to your database (like what you are doing now).
So if you Database Model looks like this -
Then you should have one viewmodel in your code in this way -
public class ImageViewModel
{
public string ImageId { get; set; }
public string ImageUrl { get; set; }
public List<string> Comments { get; set; }
}
And your controller action which will return all the results should be like this -
public class ListController : Controller
{
public ActionResult Index()
{
ImageViewModel model;
using (SampleEntities entities = new SampleEntities())
{
model = (from p in entities.Images
where p.ImageId == "1"
select new ImageViewModel()
{
ImageId = p.ImageId,
ImageUrl = p.ImageUrl,
Comments = p.ImageComments.Select(pa => pa.Comment).ToList()
}).FirstOrDefault();
}
return View(model);
}
}
Finally the view which will display all the Image results -
#model MVC.Controllers.ImageViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div>
<h4>ImageViewModel</h4>
<hr />
<dl class="dl-horizontal">
<dt>
#Html.DisplayNameFor(model => model.ImageId)
</dt>
<dd>
#Html.DisplayFor(model => model.ImageId)
</dd>
<dt>
#Html.DisplayNameFor(model => model.ImageUrl)
</dt>
<dd>
#Html.DisplayFor(model => model.ImageUrl)
</dd>
<br/>
#foreach (var item in Model.Comments)
{
#item <br/>
}
</dl>
</div>
Output would be -
Your cardComment property is a list of strings; it needs to be iterated in order to be displayed. Replace:
<ol>
<li>
#item.cardComment
</li>
</ol>
with:
<ol>
#foreach (var singleComment in Model.cardComment)
{
<li>#singleComment </li>
}
</ol>
Related
In my Action I have Three LINQ SQL(Join) , two of them which is bla4,bla5 it was working until i add Third SQL which is bla6 and SQL(bla6) only going to work or executed until RMAHistory table get data/value or have data in it and RMAHistory table get value/data until than user submitted the form before that all the rows is null in RMAHistory table and in my LINQ SQL (bla6) i have Join with RMAHistory and beacuse i have interesting one column of that table.
Here is my question how can i check if SQL (bla6) its null than run/execute bla4,bla5 and than return view and if SQL(bla6) its not null than run/execute (bla4,bla5,bla6) and in the return view.
I have tried to check if modal its null or not both in view and Controller ,but i get Object reference is not set to an instance of an object and it's beacuse rmah.AntalRMA is null.
Can anyone help me or point me in the right direction!
Thanks in advance :)
Controller:
public ActionResult RMA(RMAHistory oodvm ,string id, string Varenummer, string OrdreNo)
{
var bla6 = (from sil in data.Sales_Invoice_Line
join rmah in data.RMA_History on sil.Document_No_ equals rmah.Fakturnummer
where sil.Document_No_ == id
select new RMAHistory.SingelRMAAntal
{
TotalRMA = rmah.AntalRMA
});
var col2 = data.Sales_Shipment_Line.Where(t => t.Order_No_ == OrdreNo).Where(t => t.No_ == Varenummer).Select
(t => new
{
No_ = data.Sales_Invoice_Header.Where(or => or.Order_No_ == OrdreNo).FirstOrDefault().No_,
Line = t,
Serial = data.Item_Ledger_Entry.Where(ledger => ledger.Document_No_ == t.Document_No_).Where(ledger => ledger.Document_Line_No_ == t.Line_No_).ToList(),
TrackAndTrace = data.Track_and_Trace.Where(track => track.Shipping_No_ == t.Document_No_).Select(tr => new { traceNR = tr.Track_and_Trace, tracePath = tr.Track_and_trace_path, Agent = tr.Shipping_agent }).FirstOrDefault()
});
var bla4 = col2.Select(t =>
new RMAHistory.OrdreRMA
{
//Select something
});
var bla5 = (from sih in data.Sales_Invoice_Header
join sil in data.Sales_Invoice_Line on sih.No_ equals sil.Document_No_
join item in data.Item on sil.No_ equals item.No_
join itemcat in data.ItemCategory on item.Item_Category_Code equals itemcat.Code
where sil.Document_No_ == id
&&
sil.No_ == Varenummer
&&
sih.Order_No_ == OrdreNo
select new RMAHistory.InvoiceOrdreLineSingel
{
//Select something
});
oodvm.OrdreRMAs = bla4.FirstOrDefault();
oodvm.InvoiceDetailsSingelLine = bla5.FirstOrDefault();
oodvm.SingelRMAAntals = bla6.FirstOrDefault();
return View(oodvm);
}
RMAHistory ViewModel:
public class RMAHistory
{
public SingelRMAAntal SingelRMAAntals { get; set; }
public class SingelRMAAntal
{
public SingelRMAAntal()
{
}
public SingelRMAAntal(string TotalRMA)
{
this.TotalRMA = TotalRMA;
}
public string TotalRMA { get; set; }
}
}
View:
#using NameSpace.Models
#model RMAHistory
<div class="content">
<form id="RMAForm">
<input type="text" id="Kundenavn" value="#Model.InvoiceDetailsSingelLine.Kundenavn">
<br/>
<input id="Ordrenummer" type="text" value="#Model.InvoiceDetailsSingelLine.Ordrenummer">
<br/>
if (Model.SingelRMAAntals.TotalRMA == null)
{
<div style="display:none;" class="col-md-3">
<input name="Antal_RMA" id="Antal_RMA" value="#Model.SingelRMAAntals.TotalRMA">
</div>
}
else
{
<div class="col-md-3">
<input name="Antal_RMA" id="Antal_RMA" value="#Model.SingelRMAAntals.TotalRMA">
</div>
}
</form>
</div>
Change your view to look like below
#using NameSpace.Models
#model RMAHistory
<div class="content">
<form id="RMAForm">
<input type="text" id="Kundenavn" value="#Model.InvoiceDetailsSingelLine.Kundenavn">
<br/>
<input id="Ordrenummer" type="text" value="#Model.InvoiceDetailsSingelLine.Ordrenummer">
<br/>
if (Model != null)
{
if (Model.SingelRMAAntals != null)
{
if (Model.SingelRMAAntals.TotalRMA == null)
{
<div style="display:none;" class="col-md-3">
<input name="Antal_RMA" id="Antal_RMA" value="#Model.SingelRMAAntals.TotalRMA">
</div>
}
else
{
<div class="col-md-3">
<input name="Antal_RMA" id="Antal_RMA" value="#Model.SingelRMAAntals.TotalRMA">
</div>
}
}
}
</form>
</div>
I'm new to the world of ASP.Net MVC and I'm working with a small application that uses many XML files from a web service as its model data. I have an Html page which contains a list of all the tools that are stored in the XML web services. They are within a loop and are clickable links. I also have a partial view which is just a series of text boxes. My goal is to populate the text boxes with information I get from the tool I click while having the list and the text boxes appear on the same page. I have been successful in doing this but so far have only been able to pass the id to a controller which returns my partial view as a completely new page. I'm sure this is a simple solution which may have been answered on here before. What is the best way to go about solving this problem? Below is my model, view(s) and two controllers
Tool Model
public class Tool
{
public int Id { get; set; }
public string ToolId { get; set; }
public string Adapter { get; set; }
public string Description { get; set; }
public string TNumber { get; set; }
public List<string> ComponentList { get; set; }
public List<string> AccessoryList { get; set; }
public List<KeyValuePair<string, string>> ToolIdDescription { get; set; }
public List<string> toolList = new List<string>();
}
Partial View Controller
public ActionResult PartialView()
{
Tool newTool = new Tool();
List<string> tools = new List<string>();
tools = backgroundLoad();
newTool.ToolIdDescription = new List<KeyValuePair<string, string>>();
atool.ToolIdDescription = new List<KeyValuePair<string, string>>();
foreach (string tool in tools)
{
newTool.ToolIdDescription = GetToolDescription(tool);
}
return View(newTool);
}
Controller to recieve Datasets
public ActionResult GetDataSet(string id)
{
Tool selectedTool = new Tool();
if (id != null)
{
var request =
(HttpWebRequest)WebRequest.Create("http://localhost/DbService/Tool/" + id);
XmlDocument xml = new XmlDocument();
Stream aResponsestream;
string aResult = "";
using (aResponsestream = request.GetResponse().GetResponseStream())
using (StreamReader aReader = new StreamReader(aResponsestream,
Encoding.UTF8))
{
aResult = aReader.ReadToEnd();
aResponsestream.Close();
}
xml.LoadXml(aResult);
var Description =
xml.SelectSingleNode("RetrieveResponse/RetrieveResult/Tool/Description");
if (Description != null) selectedTool.Description =
Description.InnerText;
var Adapter =
xml.SelectSingleNode("RetrieveResponse/RetrieveResult/Tool/Adapter/Name");
if (Adapter != null) selectedTool.Adapter = Adapter.InnerText;
var TNumber =
xml.SelectSingleNode("RetrieveResponse/RetrieveResult/Tool/TNo");
if (TNumber != null) selectedTool.TNumber = TNumber.InnerText;
var ToolId =
xml.SelectSingleNode("RetrieveResponse/RetrieveResult/Tool/ToolId");
if (ToolId != null) selectedTool.ToolId = ToolId.InnerText;
return View(selectedTool);
}
else return View();
}
View which contains the list
#model MiniWeb.Models.Tool
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="~/Content/Site.css" rel="stylesheet" />
</head>
<body>
<h2>Tool List</h2>
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Id</th>
<th>Description</th>
</tr>
</thead>
#foreach (var item in Model.ToolIdDescription)
{
<tbody>
<tr>
<td>#Html.ActionLink(item.Key, "GetDataSet", new { id = item.Key })</td>
<td>#Html.DisplayFor(modelItem => item.Value)</td>
</tr>
</tbody>
}
</table>
</div>
</body>
</html>
#Html.Partial("GetDataSet", new MiniWeb.Models.Tool())
View which displays the tool information
#model MiniWeb.Models.Tool
#{
ViewBag.Title = "GetDataSet";
}
#{
ViewBag.Title = "Tool";
}
<link href="~/Content/Site.css" rel="stylesheet" />
<h2>Tool Selection </h2>
<div class="Tool">
<span id ="id">
#Html.LabelFor(m => Model.ToolId)
#Html.TextBoxFor(modelItem => Model.ToolId)
</span>
<br/>
<span id="Description">
#Html.LabelFor(m => Model.Description)
#Html.TextBoxFor(modelItem => Model.Description)
</span>
<br/>
<span id="Adapter">
#Html.LabelFor(m=> Model.Adapter)
#Html.TextBoxFor(modelItem => Model.Adapter)
</span>
<br/>
<span id="Adapter">
#Html.LabelFor(m => Model.TNumber)
#Html.TextBoxFor(modelItem => Model.TNumber)
</span>
<span>
<button> Save </button>
</span>
</div>
Sorry for all the code but thank you for reading. I also apologize if this is a really easy solution. I'm just new to ASP.Net and want to develop the best practices instead of doing a hack job on it. Thanks for the help.
With some more research I was able to figure out how to solve my problem. Turns out all I needed was some AJAX. I used an Ajax.Actionlink instead of an HTML action link and was able to load up my partial view in a div on the page. Here is my new view and controller. The partial view stayed the same.
View
#model MiniWeb.Models.Tool
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="~/Content/Site.css" rel="stylesheet" />
<script src="~/Scripts/jquery-3.1.1.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
</head>
<body>
<h2>Tool List</h2>
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Id</th>
<th>Description</th>
</tr>
</thead>
#foreach (var item in Model.ToolIdDescription)
{
<tbody>
<tr>
<td>#Ajax.ActionLink(item.Key, "_Partially", new { id = item.Key },new AjaxOptions()
{
HttpMethod = "GET",
UpdateTargetId = "ToolInfo",
InsertionMode = InsertionMode.Replace,
})
</td>
<td>#Html.DisplayFor(modelItem => item.Value)</td>
</tr>
</tbody>
}
</table>
</div>
</body>
</html>
<div id="ToolInfo">
</div>
and my new controller which is returns a PartialView looks like this
Partial View Controller
public PartialViewResult _Partially(string id)
{
Tool selectedTool = new Tool();
if (id != null)
{
var request = (HttpWebRequest)WebRequest.Create("http://localhost/DbService/Tool/" + id);
XmlDocument xml = new XmlDocument();
Stream aResponsestream;
string aResult = "";
using (aResponsestream = request.GetResponse().GetResponseStream())
using (StreamReader aReader = new StreamReader(aResponsestream, Encoding.UTF8))
{
aResult = aReader.ReadToEnd();
aResponsestream.Close();
}
xml.LoadXml(aResult);
var Description = xml.SelectSingleNode("RetrieveResponse/RetrieveResult/Tool/Description");
if (Description != null) selectedTool.Description = Description.InnerText;
var Adapter = xml.SelectSingleNode("RetrieveResponse/RetrieveResult/Tool/Adapter/Name");
if (Adapter != null) selectedTool.Adapter = Adapter.InnerText;
var TNumber = xml.SelectSingleNode("RetrieveResponse/RetrieveResult/Tool/TNo");
if (TNumber != null) selectedTool.TNumber = TNumber.InnerText;
var ToolId = xml.SelectSingleNode("RetrieveResponse/RetrieveResult/Tool/ToolId");
if (ToolId != null) selectedTool.ToolId = ToolId.InnerText;
return PartialView("_Partially", selectedTool);
}
return PartialView();
}
Hopefully this answer will help others like me in the future. Thanks for reading.
You're going to want to create a form on your partial view that will submit the data to the main pages controller.
You can find more information in this article.
I trying to create ImageBrowser in Asp.net MVC 5. Problem is when I try to switch to another picture.
Here's my code:
In View:
#model Katalog.Models.Model
#{
Model.enumerator = 0;
int count = Model.ImageList.Count;
int index = 1;
}
....
<table>
<tbody>
<tr>
<td> #index/#count </td>
....
</tr>
<tr>
#using (Html.BeginForm("previous", "Home",FormMethod.Post))
{
<td>
<input type="hidden" name="number" value="1" />
<input value="<" type="submit" onclick="ImageLeft()" class="buttonLeftRight"/>
</td>
}
<td>#{Html.RenderPartial("~/Views/Shared/ImageViews.cshtml", Model);}</td>
<td>
#using (Html.BeginForm("next", "Home", FormMethod.Post))
{
#Html.HiddenFor(a => a.ImageList)
#Html.HiddenFor(a => a.enumerator)
<input type="submit" class="buttonLeftRight" onclick="ImageRight()"/>
}
</td>
</tr>
</tbody>
</table>
....
<script>
function ImageRight()
{
#{ Model.enumerator++; }
}
</script>
My Controller
....
public ActionResult next(Katalog.Models.Model model)
{
model = MyModel;
return View("Searcher",model);
}
....
and my PartialView:
#model Katalog.Models.Model
<img id="foto" class="imgFinded" src="#Model.ImageList[#Model.enumerator]"/>
When I click Next button my model.ImageList is empty. Why?
The reason your models ImageList property is null is because your generating a hidden input #Html.HiddenFor(a => a.ImageList) which generates
<input name="ImageList" value="System.Collections.Generic.List[]String" .. />
which will not bind to your collection in the POST method (when something is not binding, always insect the name and value attribute of the form controls your generating.
In order to bind to that list you would need to generate an input for each item in the list using a loop.
The other issue is that your scripts does nothing at all. Your model is server side code, and you cannot increment the value of a model property using javascript - you need to send a request to the controller to do that.
Since you sending the collection of images to the view, there is no need to make a request back to the server - you can just update the src attribute of the <img> tag.
Change the model to
public class Model
{
public int InitialIndex { get; set; }
public int ImageCount { get { return ImageList.Count; } }
public List<string> ImageList { get; set; }
}
and then the view can be just (the partial is unnecessary)
<img id="foto" class="imgFinded" src="#Model.ImageList[#Model.InitialIndex ]"/>
<button type="button" id="previous">Previous</button>
<button type="button" id="next">Next</button>
and the scripts
var imagelist = #Html.Raw(Json.Encode(Model.ImageList));
var index = #Html.Raw(Json.Encode(Model.InitialIndex));
var max = #Html.Raw(Json.Encode(Model.ImageCount));
var image = $('#foto');
// Set the initial state of the buttons
if (index === 0) {
$('#previous').prop('disabled', true);
} else if (index === max) {
$('#previous').prop('disabled', true);
}
$('#next').click(function() {
$('#previous').prop('disabled', false);
index++;
image.attr('src', imagelist[index]);
if (index === max) {
$(this).prop('disabled', true);
}
})
$('#previous').click(function() {
$('#next').prop('disabled', false);
index--;
image.attr('src', imagelist[index]);
if (index === 0) {
$(this).prop('disabled', true);
}
})
The code #{Model.enumerator++;} and #{Model.enumerator--;} within the two Javascript functions is server side code so it will only be executed once when the view is rendering on the server and before it is passed to the client browser. So triggering the onclick="ImageRight()" by pressing the submit button will not change the server side value.
You could instead try to post the current index to the action in your controller and increment or decrement it depending on which action has been invoked.
#using (Html.BeginForm("Next", "Home", FormMethod.Post))
{
#Html.HiddenFor(a=>a.CurrentIndex)
<input type="submit" class="buttonRightLeft"/>
}
#using (Html.BeginForm("Previous", "Home", FormMethod.Post))
{
#Html.HiddenFor(a=>a.CurrentIndex)
<input type="submit" class="buttonLeftRight"/>
}
public ActionResult Next(int CurrentIndex)
{
// Get the NEXT image and return as model
model = MyModel;
return View("Searcher",model);
}
public ActionResult Previous(int CurrentIndex)
{
// Get the PREVIOUS image and return as model
model = MyModel;
return View("Searcher",model);
}
We're developing news website we're confused with some concept of usage. I'd like to ask and know better if possible. We've a homepage which may contain a lot of models at once so we're separating our homepage to partial views and we're planning to feed them with the appropriate models.
In one partial we're enumerating in categories that are not marked as deleted and we've two types of categories. One of them displays the latest post and the other displays 4 posts at once. We've achieved this actually but as i've mentioned we would like to know if there is a better way or if we're doing anything wrong because right now we're keeping the connection to the context open until the partial is rendered.
Here is the code for views
Partial View Code (CategoryRepeater.cshtml)
#using SosyalGundem.WebUI.DatabaseContext;
#{
var categoryList = new List<PostCategories>();
var db = new SosyalGundemDb();
categoryList = db.PostCategories.Include("Posts").Where(x => !x.IsDeleted).ToList();
}
#for (int i = 0; i < categoryList.Count; i++)
{
if (i % 3 == 0 || i == 0)
{
#Html.Raw("<div class=\"row-fluid spacer\">")
}
var category = categoryList[i];
if (category.PostCategoryType == 1)
{
<div class="span4">
<h3 class="title"><span>#category.PostCategoryName</span></h3>
#{
var article = category.Posts.FirstOrDefault();
if (article != null)
{
<article class="post">
<div class="entry clearfix">
<div class="span6">
<a href="#" title="Permalink to Suspen disse auctor dapibus neque pulvinar urna leo" rel="bookmark">
<img width="225" height="136" src="#Url.Content("~/Content/uploadedimages/" + article.Media.ToList()[0].MediaContent )" alt="shutterstock_70184773" />
</a>
</div>
<div class="span6">
<h4 class="smallnewstitle">#article.PostTitle</h4>
<p>#(article.PostSummary.Length > 100 ? article.PostSummary.Substring(0, 100) : article.PostSummary)</p>
<div class="meta">
<span class="date">#article.PostDate.ToString("MMMM dd, yyyy")</span>
</div>
</div>
</div>
</article>
}
}
</div>
}
else
{
<div class="video-box widget span4">
<h3 class="title"><span>#category.PostCategoryName</span></h3>
#{
int cati = 0;
var firstPost = category.Posts.OrderByDescending(x => x.PostDate).FirstOrDefault();
}
#if (firstPost != null)
{
<h4 class="smallnewstitle">#firstPost.PostTitle</h4>
<p>#(firstPost.PostSummary.Length > 100 ? firstPost.PostSummary.Substring(0, 100) : firstPost.PostSummary) </p>
<ul>
#foreach (var item in category.Posts.OrderByDescending(x => x.PostDate))
{
if (cati <= 3)
{
<li>
<a href="#" title="#item.PostTitle" rel="bookmark">
<img width="225" height="136" src="#Url.Content("~/Content/images/dummy/shutterstock_134257640-225x136.jpg")" alt="shutterstock_134257640" />
</a>
</li>
}
else
{
break;
}
cati++;
}
</ul>
}
</div>
}
if (i % 3 == 0 && i != 0)
{
#Html.Raw("</div>")
}
}
#{
db.Dispose();
}
Separate your concerns. You can see this project for start: http://www.codeproject.com/Tips/617361/Partial-View-in-ASP-NET-MVC
Controller
#using SosyalGundem.WebUI.DatabaseContext;
public ActionResult SomeAction()
{
var model = new CategoriesModel
{
NotDeletedCategories = db.PostCategories.Include("Posts").Where(x => !x.IsDeleted).ToList(),
DeletedCategories = db.PostCategories.Include("Posts").Where(x => x.IsDeleted).ToList()
};
return View(model);
}
Model
public class CategoriesModel
{
public List<PostCategories> NotDeletedCategories {get;set;}
public List<PostCategories> DeletedCategories {get;set;}
};
View
#model CategoriesModel
#Html.RenderPartial("DeletedCategories", Model.DeletedCategories)
#Html.RenderPartial("NotDeletedCategories", Model.NotDeletedCategories)
Hi Jinava,
I would suggest bind Model to the View,
Like,
public ActionResult CategoryRepeater()
{
var multiViewModel = new MultiViewModelModel
{
ModelForParialView1= new XYZ(),
ModelForParialView2= new PQR()
};
return View(model);
}
For the View
#model MultiViewModelModel
And then PAss the views with the MultiViewModelModel.ModelForParialView1 and MultiViewModelModel.ModelForParialView2
You can perform all the model operations on the view.
And at the controller level perform all the database operations and release the database connection there itself no need to get that on the view.
Hope this explanation helps you.
I'm trying to build an inbox that is very similar to facebooks message inbox, where you have a list of conversations(I only want a list of a message title) and when you click the conversation or message title in my situation, I want the whole message to be rendered next to it in a partial view.
Here's my Inbox view:
#model BlocketProject.Models.ViewModels.ProfilePageViewModel
#{
ViewBag.Title = "Inbox";
}
<h2>Dina meddelanden:</h2><br />
<div class="left">
<table id="messageTable">
#foreach (var message in Model.UserMessages)
{
<tr>
<td>
<button type="submit" class="messageButton">
#if (message.Unread == true)
{
<h4 style="font-weight:bold;">#message.MessageTitle</h4>
}
else if (message.Unread == false)
{
<h4>#message.MessageTitle</h4>
}
</button>
</td>
</tr>
}
</table>
</div>
<div class="right">
#Html.Partial("ReadMessage")
</div>
When I click this message-element that is a button, I want to pass that messageId to the PartialView ReadMessage:
#model BlocketProject.Models.DbClasses.DbMessages
<h2>#Model.MessageTitle</h2><br />
<p>#Model.MessageText</p>
and the controller looks like this:
[HttpPost]
public ActionResult Inbox()
{
var allMessages = ConnectionHelper.GetAllMessages(ConnectionHelper.GetUserByEmail(User.Identity.Name).UserId);
var model = new ProfilePageViewModel();
model.UserMessages = allMessages;
return View("Inbox", model);
}
[HttpPost]
public ActionResult ReadMessage(int messageId)
{
var model = ConnectionHelper.GetMessageByMessageId(messageId);
return PartialView("ReadMessage", model);
}
I've tried passing the messageId through a post as you can see in my controller, but then the partialView is returned as a new page and I simply want to render it in the Inbox view.
Any ideas?
EDIT:
Jonesy's answer fixed my problem when I edited it like this:
Controller:
public ActionResult ReadMessage(int messageId)
{
var model = ConnectionHelper.GetMessageByMessageId(messageId);
return PartialView("ReadMessage", model);
}
View:
<div class="left">
<table id="messageTable">
#foreach (var message in Model.UserMessages)
{
<tr>
<td>
#using (Ajax.BeginForm("ReadMessage", new { #messageId = message.MessageId }, new AjaxOptions { UpdateTargetId = "showMessage" }, FormMethod.Post))
{
<button type="submit" class="messageButton">
#if (message.Unread == true)
{
<h4 style="font-weight:bold;">#message.MessageTitle</h4>
}
else if (message.Unread == false)
{
<h4>#message.MessageTitle</h4>
}
</button>
}
</td>
</tr>
}
</table>
</div>
<div class="right" id="showMessage">
#Html.Partial("ReadMessage", new BlocketProject.Models.DbClasses.DbMessages())
</div>
Razor is run on the server, before the page is rendered. Once the page is on the client, and they can click a message, the concept of the PartialView is gone - it's all just one HTML page.
The easiest way for you to do this is to use an Ajax.BeginForm where your button is, and on click, update an element with a partial view retrieved from the server. Something like:
#using(Ajax.BeginForm("ReadMessage", "Messages", new AjaxOptions() { UpdateTargetId = "showMessage" })) {
//...
}
//...
<div class="right" id="showMessage">
//ReadMessage partial rendered on button click
</div>
A little method that could help you :
protected ActionResult View(string viewName, object model)
{
if (ControllerContext.IsChildAction)
return PartialView(viewName, model);
else if (Request.IsAjaxRequest())
return PartialView(viewName, model);
else
return View(viewName, model);
}
This will return a PartialView when you call you action via #Html.RenderAction() or call the action via Ajax (jQuery).
You can then use jQuery to prevent the form to be posted and post it with Ajax or when you click on a message, you can also use jQuery to get the result from the action and insert it in your DOM.