Failing to reference another model in my view asp.net mvc - asp.net

I am trying to display Youtube videos in my landing page. I know the code works because in another view it works.
In my landing page I am referencing a model that calls my blog posts and so I cant reference another model in my landing page
The error i get says the current model doesn't contain 'GetEnumerator'. If i add another model, I get an error saying a view can only reference one model.
This is how I display my blog posts and video in the landing page with 'model ' and 'videos'.
public ActionResult landing()
{
var model = new Stream.FeedViewModel();
var videos = WeLove.Net.Models.Stream.YouTubeHelper.GetVideos();
XmlReaderSettings settings = new XmlReaderSettings();
settings.XmlResolver = null;
settings.DtdProcessing = DtdProcessing.Ignore;
settings.DtdProcessing = DtdProcessing.Parse;
using (var reader = XmlReader.Create("https://takeonemisu.wordpress.com/feed",settings))
{
var feed = SyndicationFeed.Load(reader);
foreach (var post in feed.Items.Take(3))
{
model.Posts.Add(post);
}
}
return View(model);
}
I unfortunately can only get one to run at a time in a view.
Please help

Use child actions:
Controller
[ChildActionOnly]
public ActionResult VideoList()
{
var videos = // get videos;
return PartialView(videos);
}
[ChildActionOnly] ensures that this action can only be called as a child and not directly via a URL in the browser. If you want to serve it up at a particular URL as well, you can always remove this attribute, but then you should most likely branch over boolean values of ControllerContext.IsChildAction and/or Request.IsAjaxRequest to either return a PartialView or View as needed.
VideoList.cshtml
#model Namespace.To.VideoModel
<ul>
#foreach (var video in Model)
{
<li>#video.Title</li>
}
</ul>
Obviously the partial view HTML can be whatever you want. I just made an unordered list as an example
Post View
#Html.Action("VideoList")

Related

How to make Output cache for tweetsharp twitter feeds in asp net mvc5

I am using tweetsharp nuget package for adding tweets to my website.
I put my partialview on footer and it is visible on everpage of website.
here is my codes on Basecontroller.
public PartialViewResult _PartialView_twitter_feed()
{
var service = new TwitterService("key", "key");
service.AuthenticateWith("key", "key");
IEnumerable<TwitterStatus> tweets = service.ListTweetsOnUserTimeline(new ListTweetsOnUserTimelineOptions { ScreenName="my_screen_name", Count=5 });
ViewBag.Tweets = tweets;
return PartialView();
}
and I call it like this on footer view.
#Html.Action("_PartialView_twitter_feed", "base")
Now is the question, How can I make output caching or some kind of caching for this implementation on asp net mvc 5?
I dont want to call twitter api in every page view again and again. Because partial view is on footer.
How can I make it only once and show it until user leaves my website?
What can be the best practise to achive this?
Thanks for any help.
You can use OutputCache attribute. I hope the following example will help you.
Controller
[OutputCache(Duration = 6000)]
public PartialViewResult Footer()
{
return PartialView("Footer");
}
public ActionResult MainPage1()
{
return View();
}
public ActionResult MainPage2()
{
return View();
}
View
MainPage1
<h2>MainPage1</h2>
#Html.Action("Footer")
MainPage2
<h2>MainPage2</h2>
#Html.Action("Footer")
When user access the MainPage1 first time, the Footer partial view will return from server. From second time onwards it will return from cache. Even when user access MainPage2 the footer partial view will return from cache. You can increase the duration seconds based on your requirement

How can I run code from my layout file?

I used the following tutorial to help me build an RSS Reader in my ASP.NET MVC3 Razor application:
http://weblogs.asp.net/jalpeshpvadgama/archive/2011/08/17/creating-basic-rss-reader-in-asp-net-mvc-3.aspx
However, unlike the tutorial example, I want the RSS feed to be displayed on every page, and have therefore added it to my layout file, /Views/Shared/_Layout.cshtml
I currently only have 2 views on my site, and to get the RSS Reader to work on both views I've got the following code in my HomeController:
public class HomeController : Controller
{
//
// GET: /Index/
public ActionResult Index()
{
return View(CT.Models.RssReader.GetRssFeed());
}
public ActionResult About()
{
return View(CT.Models.RssReader.GetRssFeed());
}
}
From my WebForms experience, I would simply add the RSS Reader code in my master page code behind, and it would automatically work on every page.
Is there a Controller for layout pages which allows me to do the same?
How can I get this to work on every call of the layout page, without having to return anything?
EDIT: Following #Sebastian's advice, I've now added this code to a Partial View, removed CT.Models.RssReader.GetRssFeed() from return View() and included this in my layout file:
#Html.Partial("_MyPartialView")
The code in this partial view is:
<ul>
#foreach (var item in Model)
{
<li>
#item.Title
</li>
}
</ul>
However, I'm not getting a runtime error:
Object reference not set to an instance of an object.
It's erroring on the line #foreach (var item in Model)
You have to create a partial view and add functionality there.
Then in your layout, render this partial.
EDIT
Is your partial view really a partial view? The reason I said that is because you have "_" in front of the name which suggests that it might be a layout (might just be a naming convention).
To fix object reference error, you have to add the #Model declaration on top of your partial view.
Hope it helps.
UPDATE
In order to use different model in partial view, you need to explicitly declare which model you are going to use on render partialmethod.
#{Html.RenderPartial("../YourFeed", Model.YourFeedModel);}
Let me know if that resolved your issue.
The new error you are having is due to you not passing a Model to the partial view. You can do this with the second argument of the Html.Partial function...
Html.Partial("ViewName", MyModel);
As I think you are trying to do this in a Layout page you could also consider using a static reference to get your RSS feed. So forget about needing to pass in a Model and in your partial have:
#foreach (var item in RssRepository.GetFeed())
{
<li>
#item.Title
</li>
}
this like to a class something like...
public static RssRepository
{
public static MyModel GetFeed()
{
return new MyModel();//<- return what you would normally pass as a Model for RSS feeds
}
}
Hope that all makes sense

Asp.Net MVC Return to page on error with fields populated

I am starting a new project in Asp.net MVC 2.
I have been mostly a webforms developer and have limited exposure to Asp.Net MVC and hence this is probably a noob question.
My situation is as follows:
I have a create page for saving some data to the DB.
The view for this page is not strongly bound / typed - so the way I am extracting the data from the view is by looking at the POST parameters.
Incase there is an error (data validation, etc), I need to send the user back to the previous page with everything filled in the way it was and displaying the message.
On webforms, this got handled automatically due to the view state - but how can I go about doing the same here?
A code example can be as follows:
View:
<% using (Html.BeginForm("Create", "Question", FormMethod.Post)) { %>
<div>
Title: <%: Html.TextBox("Title", "", new { #style="width:700px" })%>
</div>
<div>
Question: <%: Html.TextBox("Question", "", new { #style="width:700px" })%>
</div>
<input type="submit" value="Submit" />
<% } %>
Controller:
[HttpPost]
[ValidateInput(false)]
public ActionResult Create() {
Question q = new Question();
q.Title = Request.Form["Title"];
q.Text = Request.Form["Question"];
if(q.Save()) {
return RedirectToAction("Details", new { id = q.Id });
}
else {
// Need to send back to Create page with data filled in
// Help needed here
}
}
Thanks.
You could simply return the View in case of error. This will preserve the context.
[HttpPost]
[ValidateInput(false)]
public ActionResult Create(Question q) {
if(q.Save()) {
return RedirectToAction("Details", new { id = q.Id });
}
else {
// Need to send back to Create page with data filled in
// Help needed here
return View();
// If the view is located on some other controller you could
// specify its location:
// return View("~/Views/Question/Create.aspx");
}
}
Also I would recommend you to use strongly typed views along with the strongly typed helpers. Notice how I used a Question object directly as action parameter. This is equivalent to the code you have written in which you were manually extracting and building this object. The model binder does this job automatically for you.

Html.ActionLink in Partial View

I am using the following code in my master page:
<% Html.RenderAction("RecentArticles","Article"); %>
where the RecentArticles Action (in ArticleController) is :
[ChildActionOnly]
public ActionResult RecentArticles()
{
var viewData = articleRepository.GetRecentArticles(3);
return PartialView(viewData);
}
and the code in my RecentArticles.ascx partial view :
<li class="title"><span><%= Html.ActionLink(article.Title, "ViewArticle", new { controller = "Article", id = article.ArticleID, path = article.Path })%></span></li>
The problem is that all the links of the articles (which is built in the partial view) lead to the same url- "~/Article/ViewArticle" .
I want each title link to lead to the specific article with the parameters like I'm setting in the partial view.
Thanks.
I think your not using the ActionLink correctly. Change the ActionLink code to:
Html.ActionLink(
article.Title,
"ViewArticle",
"Article", // put the controller here
new
{
id = article.ArticleID,
path = article.Path
},
null)
Notice the null at then end.
EDIT: Why are you using [ChildActionOnly] in your controller? Since it is an MVC 2 feature I am assuming that you are using MVC2? Try removing it and check out the following article:
http://www.davidhayden.me/2009/11/htmlaction-and-htmlrenderaction-in-aspnet-mvc-2.html
I think the issue has to do with your partial not rendering. I would start by just trying to verify that your partial is rendering properly. Once you confirm that start to debug why the partial is not outputing.
I was able to solve the problem by using the following call in my RecentArticles action:
return PartialView("~/Views/Shared/Article/RecentArticles.ascx", viewData);
It seems like the partial view was not being rendered at all,
Thanks !

Retrieving data from Html.DropDownList() in controller (ASP MVC) | string returned?

I have the following problem:
I have a form in site/banen (currently local running webserver) which is using a SQL database. The link is made using ADO.net and is instantiated in the controller in the following way:
DBModelEntities _entities;
_entities = new DBModelEntities(); // this part is in the constructor of the controller.
Next, I use this database to fill a Html.DropDownList() in my view. This is done in two steps. At the controller side we have in the constructor:
ViewData["EducationLevels"] = this.GetAllEducationLevels();
and a helper method:
public SelectList GetAllEducationLevels()
{
List<EducationLevels> lstEducationLevels = _entities.EducationLevels.ToList();
SelectList slist = new SelectList(lstEducationLevels, "ID", "Name");
return slist;
}
In the view I have the following:
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<!-- various textfields here -->
<p>
<label for="EducationLevels">EducationLevels:</label>
<!-- <%= Html.DropDownList("EducationLevels", ViewData["EducationLevels"] as SelectList)%> -->
<%= Html.DropDownList("EducationLevels", "..select option..")%>
</p>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
Now, the form is rendered correctly when I browse to the create page. I can select etc. But when selected I have to use that value to save in my new model to upload to the database. This is where it goes wrong. I have the following code to do this in my controller:
//
// POST: /Banen/Create
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(FormCollection form)
{
// set rest of information which has to be set automatically
var vacatureToAdd = new Vacatures();
//vacatureToAdd.EducationLevels = form["EducationLevels"];
// Deserialize (Include white list!)
TryUpdateModel(vacatureToAdd);
// Validate
if (String.IsNullOrEmpty(vacatureToAdd.Title))
ModelState.AddModelError("Title", "Title is required!");
if (String.IsNullOrEmpty(vacatureToAdd.Content))
ModelState.AddModelError("Content", "Content is required!");
// Update the variables not set in the form
vacatureToAdd.CreatedAt = DateTime.Now; // Just created.
vacatureToAdd.UpdatedAt = DateTime.Now; // Just created, so also modified now.
vacatureToAdd.ViewCount = 0; // We have just created it, so no views
vacatureToAdd.ID = GetGuid(); // Generate uniqueidentifier
try
{
// TODO: Add insert logic here
_entities.AddToVacatures(vacatureToAdd);
_entities.SaveChanges();
// Return to listing page if succesful
return RedirectToAction("Index");
}
catch (Exception e)
{
return View();
}
}
#endregion
It gives the error:
alt text http://www.bastijn.nl/zooi/error_dropdown.png
I have found various topics on this but all say you can retrieve by just using:
vacatureToAdd.EducationLevels = form["EducationLevels"];
Though this returns a string for me. Since I'm new to ASP.net I think I am forgetting to tell to select the object to return and not a string. Maybe this is the selectedValue in the part where I make my SelectList but I can't figure out how to set this correctly. Of course I can also be complete on a sidetrack.
Sidenote: currently I'm thinking about having a seperate model like here.
Any help is appreciated.
You can't return an object from usual <SELECT> tag wich is rendered by Html.DropDownList() method, but only string variable could be returned. In your case ID of EducationLevels object will be send to the server. You should define and use one more custom helper method to reconstruct this object by ID.

Resources