Guys I am trying to generate notices on my test web application for learning MVC. This has functionality same as facebook's newsfeed. I have created a model of notice, a partial view of notice and executing a stored procedure in controller to retrieve the values from database (SQL server 2012).
Now what I want to do is, upon loading the page, it should display 3 notices (partial view repeated 3 times with different values each time) and then on scroll event it should load 5 more notices..
This is my model :
public class Notice
{
public string Subject { get; set; }
public DateTime Date { get; set; }
public string Department { get; set; }
public string Body { get; set; }
public string NoticeImage { get; set; }
public string Icon { get; set; }
}
This is my partial view :
<article class="feed payroll new" data-slide="items1">
<div class="sideicon"><img src="#Model.notice.Icon" alt="payroll" width="52" height="52"></div>
<section>
<header>
<h3> #Model.notice.Subject</h3>
<p><span> #Model.notice.Department</span> | #Model.notice.Date </p>
</header>
<article>
#Model.notice.Body
<br />
<img src="#Model.notice.NoticeImage" width="100" height="100"/>
</article>
</section>
</article>
This is my controller :
Query = "uSP_GetNotices";
cmd = new SqlCommand(Query, Connection);
cmd.CommandType = CommandType.StoredProcedure;
DataTable dtNotice = new DataTable();
Connection.Open();
dtNotice.Load(cmd.ExecuteReader());
Connection.Close();
Notice objNotice = new Notice();
objNotice.Subject = dtNotice.Rows[0]["Subject"].ToString();
objNotice.Date = Convert.ToDateTime(dtNotice.Rows[0]["IssueDate"]);
objNotice.Department = dtNotice.Rows[0]["Department"].ToString();
objNotice.Body = dtNotice.Rows[0]["Body"].ToString();
objNotice.NoticeImage = dtNotice.Rows[0]["NoticeImage"].ToString();
objNotice.Icon = dtNotice.Rows[0]["Icon"].ToString();
//returning Main view....
Now how do I go about getting that functionality ? how do I repeating partial view multiple times with different values each time ?
In the above code, I am only entering row 0 of datatable to model...I want to do this dynamically i.e. change rows per partial view. I would really appreciate some help.
EDIT :
NoticeUserWrapper
public class NoticeUserWrapper
{
public User user;
public List<Notice> noticeList;
public NoticeCount noticeC;
public NoticeUserWrapper()
{
user = new User();
noticeList = new List<Notice>();
noticeC = new NoticeCount();
}
}
Pass the List to main view and then in loop call Html.RenderPartial like this:
#model List<NameSpace.Models.Notice>
#forach(var item in Model)
{
Html.RenderPartial("YourPartialView", item)
}
Partial View:
#model NameSpace.Models.Notice
<article class="feed payroll new" data-slide="items1">
<div class="sideicon"><img src="#Model.notice.Icon" alt="payroll" width="52" height="52"></div>
<section>
<header>
<h3> #Model.notice.Subject</h3>
<p><span> #Model.notice.Department</span> | #Model.notice.Date </p>
</header>
<article>
#Model.notice.Body
<br />
<img src="#Model.notice.NoticeImage" width="100" height="100"/>
</article>
</section>
</article>
UPDATED:
You need to use jquery and ajax to achieve this, i implemented this in my one project and made a tutorial you can see here:
http://developmentpassion.blogspot.com/2013/12/infinite-scroll-paging-in-aspnet-mvc-4.html
You can do using ajax:
//you method on the controller
public ActionResult GetNotice(Param param)
{
//retrive notice
IList<Notice> viewModels = GetNotices();
return PartialView("_NoticePartial",viewModels)
}
JavaScript:
$(document).ready(function()
{
//ID of your div
$("#mynotices").scroll(function() {
var param = "your param";
$.post("/Notice/GetNotice",{param: param}, function(data) {
$("mynotices").append(data);//append all notice retrieved from your controller
});
});
});
the partial view
#model IList<Notice>
#foreach(item in Model)
{
<article class="feed payroll new" data-slide="items1">
<div class="sideicon"><img src="#Model.notice.Icon" alt="payroll" width="52" height="52"></div>
<section>
<header>
<h3> #item.notice.Subject</h3>
<p><span> #item.notice.Department</span> | #item.notice.Date </p>
</header>
<article>
#item.notice.Body
<br />
<img src="#item.notice.NoticeImage" width="100" height="100"/>
</article>
</section>
</article>
}
Index page:
<div id="mynotices">
//your notice
</div>
Related
I checked all the solutions but still doesnt work.I got a partial view page in layout page and When ı run only partial page it works but when ı run another page with layout it doesnt work.
I hope you can help me
Here is my Model :
public CheckListType CheckListType { get; set; }
public IEnumerable<SelectListItem> CheckListTypeList1 { get; set; }
And my Controller :
public ActionResult ListCheckListType()
{
ControlListTypeModel listTypeModel = new ControlListTypeModel();
List<SelectListItem> CheckListTypeList = new List<SelectListItem();
foreach (CheckListType item in checklisttypeRepository.List().ProcessResult)
{
CheckListTypeList.Add(new SelectListItem { Value = item.CheckListTypeId.ToString(), Text = item.CheckListType1 });
}
listTypeModel.CheckListTypeList1 = CheckListTypeList;
return PartialView("~/Areas/User/Views/CheckList/ListCheckListType.cshtml", listTypeModel);
}
View :
#using TodoListApp.Areas.User.Models.ViewModel
#model ControlListTypeModel
<form action="/CheckList/ListCheckListType" method="get">
<div>
CheckListType :
</div>
<div>
#Html.DropDownListFor(modelitem=>modelitem.CheckListType.CheckListTypeId,Model.CheckListTypeList1)
<button type="button" class="butt button bg-info" style="height:40px; width:98px;">Choose CheckListType</button>
</div>
Layout :
<div class="container body-content">
#Html.Action("ListCheckListType");
#RenderBody(){
}
<hr />
<footer>
<p> #DateTime.Now.Year </p>
</footer>
</div>
HttpException: A public action method 'ListCheckListType' was not found on controller
The problem occurs because it searches ListCheckListType action in wrong controller while rendered in partial view. Specifying controller name as well should fix the exception
#Html.Action("ListCheckListType", "Home"); //if action is in HomeController
I have two model classes,
public class Claims //Goes into main view
{
public int Id { get; set; }
public string ClaimName { get; set; }
public List<ClaimDetails> ClaimList { get; set; }
}
public class ClaimDetails //Class I want in my partial view
{
public int ClaimNumber { get; set; }
public string Client { get; set; }
public int Amount { get; set; }
public string Type { get; set; }
}
My controller,
public class ClaimsController : Controller
{
public ActionResult Index()
{
Claims claims = new Claims();
claims.Id = 1;
claims.ClaimName = "Ashton";
return View(claims);
}
[HttpPost]
public ActionResult SearchList(string enterdNumber)//On click of button I come here using ajax call
{
ClaimDetails cD = new ClaimDetails();
Claims cms = new Claims();
cms.ClaimList = new List<ClaimDetails>();
cD.ClaimNumber = 10;
cD.Client = "Ashton";
cD.Amount = 2900;
cD.Type = "Vendor";
cms.ClaimList.Add(cD);
ClaimDetails cDD = new ClaimDetails();
cDD.ClaimNumber = 10;
cDD.Client = "Ashton";
cDD.Amount = 2900;
cDD.Type = "Vendor";
cms.ClaimList.Add(cDD);
return PartialView("SearchList",cms);
}
My main view in which I want my partial view to be rendered,
#using BusinessLayer
#model BusinessLayer.Claims
#{
ViewBag.Title = "Index";
}
<script src="~/Scripts/jquery-1.10.2.min.js" type="text/javascript"></script>
<script src="~/Scripts/bootstrap.min.js" type="text/javascript"></script>
<div class="row">
<div class="col-md-6">
#Html.LabelFor(m => m.Id):#Model.Id
</div>
<div class="col-md-6">
#Html.LabelFor(m => m.ClaimName):#Model.ClaimName
</div>
</div>
<div class="row">
<div class="col-md-6">
<input id="searchNumber" placeholder="Enter the number" type="text" />
</div>
<div class="row">
<button id="searchBtn" type="button">Search</button>
</div>
</div>
<div class="row">
<div class="col-md-12">
#Html.Partial("SearchList",Model.ClaimList)
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$("#searchBtn").on("click", function () {
var enteredNum = $("#searchNumber").val();
$.ajax({
type: "POST",
url: "/Claims/SearchList",
data: { enterdNumber: enteredNum }
});
});
});
</script>
My partial view,
#model BusinessLayer.Claims
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>Claim Number</th>
<th>Client</th>
<th>Amount</th>
<th>Type</th>
</tr>
<tbody>
#if (Model.ClaimList != null)
{
foreach(var item in Model.ClaimList)
{
<tr>
<td>#item.ClaimNumber</td>
<td>#item.Client</td>
<td>#item.Amount</td>
<td>#item.Type</td>
</tr>
}
}
</tbody>
</table>
My control comes to my partial view page, which I confirmed using breakpoint, it also iterates through the foreach loop but still does not put rows into my table..Help to know where I am going wrong is appreciated, or may be my approach to partial view is itself wrong?
You're returning a partial view but you're not doing anything with it. You need to include the success callback in the ajax function and add the partial view to the DOM
$.ajax({
type: "POST",
url: '#Url.Action("SearchList", "Claims")', // use this
data: { enterdNumber: enteredNum },
dataType: 'html', // add this
success: function(response) {
$('#someElement').html(response); // add this (adjust id to suit)
}
});
and assuming you want to update the existing partial, add an id attribute to the existing container
<div class="row">
<div class="col-md-12" id="someElement"> // add id attribute
#Html.Partial("SearchList",Model.ClaimList)
</div>
</div>
Side notes:
You may want to consider including the <table> and <thead>
element in the main view and have the partial only return the
<tbody> elements to minimize the data transfered in each ajax
call.
Your method appears to be just getting data based on a filter, so
the method could be a GET rather than a POST
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[MvcApplication1.Models.News]', but this dictionary requires a model item of type 'MvcApplication1.Models.News'.
//my Controller
public class HomeController : Controller
{
CouncilDb _db=new CouncilDb() ;
public ActionResult Index()
{
var News = _db.News
.Take(10);
var Banner = (from r in _db.Banner orderby r.id descending select r).FirstOrDefault();
maz model = new maz();
model.Banner = Banner;
model.News = News.ToList();
return View(model);
}
protected override void Dispose(bool disposing)
{
if (_db != null)
{
_db.Dispose();
}
base.Dispose(disposing);
}
}
public class maz
{
public List<News> News { get; set; }
public Banner Banner { get; set; }
}
//Index view
#model MvcApplication1.Controllers.maz
#{
ViewBag.Title = "Home Page";
}
<!-- Banner -->
<!-- Banner -->
<div id="banner">
<h2> #Model.Banner.H2</h2>
<span class="byline"> #Model.Banner.Span </span>
</div>
#Html.Partial("_News",Model.News )
//Partialview
#model MvcApplication1.Models.News
<!-- Carousel -->
<div class="carousel">
<div class="reel">
<article>
<a class="image featured">
<img src="#Model.ImgUrl " alt="" /></a>
<header>
<h3>#Html.ActionLink(#Model.Title , "serch", "Home")</h3>
</header>
<p>#Model.Body </p>
</article>
</div>
</div>
The .News property of your model is of type List<News> not News so the model declaration in your partial view and the model you are passing to it don't match.
Depending on what you want to acheive, you can either loop through the List inside the index view:
#foreach (var news in Model.News)
{
#Html.Partial("_News", news)
}
or adjust the partial view model declaration and loop there
#model List<News>
....
#for (var news in Model)
{
<article>
<a class="image featured">
<img src="#news.ImgUrl" alt="" /></a>
<header>
<h3>#Html.ActionLink(#news.Title , "serch", "Home")</h3>
</header>
<p>#news.Body</p>
</article>
}
The error is pretty straightforward, once you get past the generic syntax. In C#-speak it's saying this:
The model item passed into the dictionary is of type 'List<News>',
but this dictionary requires a model item of type 'News'.
Your partial view is declared with a #model clause that specifies an item of type News:
#model MvcApplication1.Models.News
but when you pass in data to that partial view, what you're passing in is a List<News>:
#Html.Partial("_News",Model.News)
What you probably want is a loop (a #foreach or similar) that creates one partial view for each element in your News list.
I wrote something like this in the controller.
public ActionResult Giris()
{
ViewData["Tarif"] = (from t in _entities.Tarif
join k in _entities.Kullanici on t.KID equals k.KID
select new {KAdi = k.KAdi, TAdi = t.TAdi})
.Take(4);
return View();
}
I am using it as below in the view page.
<% foreach (var item in (IEnumerable<dynamic>)ViewData["Tarif"]) { %>
<div class="begenilen-video" style="float:left">
<img class="video-resmi" alt="reklam" src="../../Uygulama/Resimler/Reklam/1.jpg" />
<span class="benzer-yemek-tarifi-adi"></span><%=item.TAdi %><br />
<span class="benzer-yemek-tarifi-ekleyen">Ekleyen: </span><br />
<span class="benzer-yemek-tarifi-izlenme">İzlenme: </span>
</div>
<% } %>
However,I am receive the error in the select statement.How do I invoke the items in the view page?
Thanks in advance.
As a guess because you haven't posted the error:
The object being stored in ViewData["Tarif"] will be of the type IQueryable<T> where T is an anonymous object and in your view you are casting to IEnumerable<dynamic>. IQueryable is also lazily loaded so you will be trying to execute your query once the object has been disposed.
You should really create a strongly typed view model
public class ViewModelType {
public IEnumerable<TarifType> Tarif { get; set; }
}
Tarif type
public class TarifType {
public string KAdi { get; set; }
public string TAdi { get; set; }
}
controller
public ActionResult Giris() {
var viewModel = new ViewModelType();
viewModel.Tarif = (from t in _entities.Tarif
join k in _entities.Kullanici on t.KID equals k.KID
select new TraifType { KAdi = k.KAdi, TAdi = t.TAdi }
).Take(4)
.ToList();
return View(viewModel);
}
view
<% foreach (var item in viewModel.Tarif) { %>
<div class="begenilen-video" style="float:left">
<img class="video-resmi" alt="reklam" src="../../Uygulama/Resimler/Reklam/1.jpg" />
<span class="benzer-yemek-tarifi-adi"></span><%=item.TAdi %><br />
<span class="benzer-yemek-tarifi-ekleyen">Ekleyen: </span><br />
<span class="benzer-yemek-tarifi-izlenme">İzlenme: </span>
</div>
<% } %>
I'm my Project Browser page I have 2 sub-elements that warrant their own controller (and not simply a user-control) - Upload and FileBrowser, and so I've added them using Html.RenderAction(Action, Controller, param).
The problem however, is that the Browse page requires ProjectViewModel, where Upload uses UploadViewModel, etc. etc. So by having these Html.RenderAction elements, the Browse page seems to immediately stop receiving the ProjectViewModel - i'm guessing it switches to the VM of the last RenderAction.
Is there something I have to set up in routing to ensure these already strongly typed Views keep their contexts?
Update with code:
Also, maybe I have to explicitly state that the model going TO "Upload" is a different one? I dunno.
Browser (containing Upload and FileBrowser):
<%#
Page Title=""
Language="C#"
Inherits="System.Web.Mvc.ViewPage<CKD.Web.Files.ViewModels.ProjectViewModel>"
MasterPageFile="~/Views/Project/Project.Master"
%>
<asp:Content runat="server" ID="Main" ContentPlaceHolderID="MainContent">
<table>
<tr>
<td id="upload" style="width: 180px" class="ui-widget ui-widget-content ui-corner-all">
<% Html.RenderAction("Index", "Upload", new {id = Model.Project.Id}); %>
</td>
<td id="fileBrowser" style="width: auto" class="ui-widget ui-widget-content ui-corner-all">
<% Html.RenderAction("Index", "FileBrowser", new {id = Model.Project.Id}); %>
</td>
</tr>
</table>
</asp:Content>
Upload View:
<%#
Page Title=""
Language="C#"
Inherits="System.Web.Mvc.ViewPage<CKD.Web.Files.ViewModels.UploadViewModel>"
MasterPageFile="~/Views/Shared/Control.master"
%>
<%# Import Namespace="System.IO" %>
<asp:Content runat="server" ID="Scripts" ContentPlaceHolderID="Scripts">
</asp:Content>
<asp:Content runat="server" ID="Main" ContentPlaceHolderID="MainContent">
<div class="uploadControl" style="Margin: 8px">
<h2 style="Margin-Bottom: 0px">Upload</h2>
<hr />
<div id="accordion" style="display: block;">
<h3>Files</h3>
<div>
<div class="ui-widget-content ui-corner-all" style="min-height: 80px; margin: 4px">
<% if(Model.Files != null) %>
<% foreach(FileInfo f in Model.Files) {%>
<p><%= f.Name %></p>
<hr />
<% } %>
</div>
<ul style="width: 10px; list-style-type:none">
<li class="ui-widget ui-widget-button ui-corners-all">Clear</li>
<li class="ui-widget ui-widget-button ui-corners-all">Add</li>
</ul>
</div>
<h3>Transmittal</h3>
<div>
<p>File here</p>
<p style="width: auto; margin: 8px" class="ui-widget-button">Pick File...</p>
</div>
<h3>Notification</h3>
<div>
<p>
Stuff
</p>
</div>
</div>
<div>
<div class="ui-widget ui-corner-all ui-widget-active">Upload Files</div>
</div>
</div>
</asp:Content>
Upload Controller:
using System.Web.Mvc;
namespace CKD.Web.Files.Controllers
{
using System.Linq;
using Models;
using ViewModels;
public class UploadController : Controller
{
private ICKDClientAreaRepository Repository { get; set; }
private UploadViewModel _viewModel;
private UploadViewModel ViewModel
{
get { return _viewModel ?? (_viewModel = ViewModel = UploadViewModel.Default(Repository)); }
set { _viewModel = value; }
}
public UploadController(ICKDClientAreaRepository repository)
{
Repository = repository;
}
// GET
public ActionResult Index(int id)
{
var project = Repository.Projects.Single(x => x.Id == id);
ViewModel = UploadViewModel.ForProject(project, Repository);
return View(ViewModel);
}
}
}
Upload VM:
namespace CKD.Web.Files.ViewModels
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web.Security;
using Models;
public class UploadViewModel
{
public Project Project { get; set; }
public DirectoryInfo Directory { get; set; }
public User Uploader { get; set; }
public DateTime Time { get; set; }
public List<FileInfo> Files { get; set; }
public FileInfo Transmittal { get; set; }
public List<User> NotificationList { get; set; }
public static UploadViewModel Default(ICKDClientAreaRepository fromRepository)
{
var project = fromRepository.Projects.First();
return ForProject(project, fromRepository);
}
public static UploadViewModel ForProject(Project project, ICKDClientAreaRepository fromRepository)
{
var dir = project.DirectoryName;
var uploader = fromRepository.Users.Single(x => x.Username == Membership.GetUser().UserName);
var time = DateTime.Now;
var notification = project.Users.ToList();
return new UploadViewModel
{
Project = project,
Directory = new DirectoryInfo(dir),
Uploader = uploader,
Time = time,
NotificationList = notification
};
}
}
}
Try making the view rendered by RenderAction() a partial view.
You should also decorate the action with [ChildActionOnly] attribute to prevent it from executing by it's own (when somebody would request http://xxx.com/Upload/Index).