Passing html id to and mvc controller - asp.net-mvc

I'm doing an game news website and I have a problem in the code. I need to the client to press a news button, choosing one of many news, and the button id, which is the news id, need to go to a controller method, then the controller will take that news and show in another view.
Here is the view code:
<div class="panel panel-default">
<div class="panel-heading">News List</div>
<table>
#foreach (var a in Model)
{
<tr>#Html.ActionLink("Read More", "Post", "Home", new { id = #a.Id }, null)</tr>
}
</table>
And here is the controller method, wich is in the HomeController:
public ActionResult Post(string id)
{
Post post = this.post.ChosePost(id);
return View(post);
}
This should call a view with the html view on the previous link but it's not, and I do change the mapRoute but isn't working at all, the value don't go to controller.

Related

How can I save form data between pages asp.net mvc?

I have a long form that's been split up into separate pages using partial views. I want to save the data entered into one partial view form when the user clicks to go to the next patial view form. Then have it so that when they come back to the previous view then the data entered will be there.
So what i need is to post the data to a controller.
Although what I am using for the partial view is:
#Ajax.ActionLink("Job Information", "JobInformation", new AjaxOptions { InsertionMode = InsertionMode.Replace, UpdateTargetId = "jobForm"})
When they click the action link it takes them to the next page (partial view)
So how can i submit the form when they click the action link?
how can i submit the form when they click the action link?
i need is to post the data to a controller.
Instead of using AJAX ActionLink use AJAX BeginForm as shown below. Lets say you have a model like below, to populate a dropdownlist.
public class DDLModel
{
public List<SelectListItem> Items { get; set; }
public string SelectedValue { get; set; }
}
Then you have controller to display this model -
#model MVC.Controllers.DDLModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
#using (Ajax.BeginForm("Submit", "Ajax", new AjaxOptions { UpdateTargetId = "SellerWebSettings" }, new { id = "form1" }))
{
#Html.DropDownListFor(m => m.SelectedValue, Model.Items, "DDL")
<input type="submit" value="Click" />
}
<div id="SellerWebSettings">
</div>
In the above form, you have a AJAX BeginForm() which would make a AJAX all to another controller action which will return a PartialView. The model will also be forwarded to the partial view, as shown below -
public ActionResult Submit(DDLModel model)
{
return PartialView("MyPartial",model);
}
And the partial view is as follows -
#model MVC.Controllers.DDLModel
<div>
#DateTime.Now - #Model.SelectedValue
</div>
So when we select the Dropdownlist item and click on the button, we have following output -

MVC 3 StackOverflowException w/ #Html.Action()

I've looked over a bunch of other reports of this, but mine seems to be behaving a bit differently. I am returning PartialViewResults for my child actions, so that's not the source of the recursion. Here's a dumbed down version of what I have.
// The Controller
[ChildActionOnly]
public ActionResult _EditBillingInfo()
{
// Generate model
return PartialView(model);
}
[HttpPost]
public ActionResult _EditBillingInfo(EditBillingInfoViewModel model)
{
// Update billing informatoin
var profileModel = new EditProfileViewModel()
{
PartialToLoad = "_EditBillingInfo"
};
return View("EditProfile", profileModel);
}
[ChildActionOnly]
public ActionResult _EditUserInfo()
{
// Generate model
return PartialView(model);
}
[HttpPost]
public ActionResult _EditUserInfo(EditUserInfoViewModel model)
{
// Update user informatoin
var profileModel = new EditProfileViewModel()
{
PartialToLoad = "_EditUserInfo"
};
return View("EditProfile", profileModel);
}
public ActionResult EditProfile(EditProfileViewModel model)
{
if (String.IsNullOrEmpty(model.PartialToLoad))
{
model.PartialToLoad = "_EditUserInfo";
}
return View(model);
}
// EditProfile View
#model UPLEX.Web.ViewModels.EditProfileViewModel
#{
ViewBag.Title = "Edit Profile";
Layout = "~/Views/Shared/_LoggedInLayout.cshtml";
}
<div>
<h2>Edit Profile</h2>
<ul>
<li class="up one"><span>#Ajax.ActionLink("Account Information", "_EditUserInfo",
new AjaxOptions { UpdateTargetId = "EditProfileDiv", LoadingElementId = "LoadingImage" })</span></li>
<li class="up two"><span>#Ajax.ActionLink("Billing Information", "_EditBillingInfo",
new AjaxOptions { UpdateTargetId = "EditProfileDiv", LoadingElementId = "LoadingImage" })</span></li>
</ul>
<img alt="Loading Image" id="LoadingImage" style="display: none;" src="../../Content/Images/Misc/ajax-loader.gif" />
<div id="EditProfileDiv">
#Html.Action(Model.PartialToLoad)
</div>
</div>
The partial views are both forms for updating either the user information or billing information.
I debugged through this and found what is happening, but cannot figure out why. When a user browses to EditProfile, it load up with the _EditUserInfo partial and the form is there for editing. When you change some info and submit the form it hangs and you get a StackOverflowException in the EditProfile view on the call to #Html.Action(). What happens is on the initial visit to EditProfile, the #Html.Action calls the HttpGet version of _EditUserInfo. You make some changes to the user info and click submit. Once the information is updated the EditProfile view is returned again, but this time #Html.Action calls the HttpPost version of _EditUserInfo which updates the user information again, returns the EditProfile view again and the #Html.Action calls the HttpPost version of _EditUserInfo... You get where this is going. Why after form submission does it call the post version and not the get version like it did for the initial visit to EditProfile?
Thanks for any help!
I might be getting this a bit wrong, it's been a long day so, but in EditProfile you set PartialToLoad (if it's empty) to "_EditUserInfo", then in _EditUserInfo you set it again to _EditUserInfo, won't this create a loop that behaves as what you are experiencing?

MVC 3 show hide Partial Views in jquery UI tabs

In our application we are using Tabs to display the information for example contacts, in this tab the user can switch between view contacts and created contact. When the user clicks on ‘Create’ I want the partial view changed to CreateContact within the same tab. What is the best way to show hide a Partial Views in jquery UI tabs? Should I use Ajax code to do this?
View
<div id="tabs">
<ul>
<li>Claim</li>
<li>Products</li>
<li>Contact Us</li>
</ul>
</div>
Controller
public ActionResult GetContact()
{
return PartialView();
}
public ActionResult CreateContact()
{
return PartialView();
}
Partial View
<li>#Html.ActionLink("Create", "Test", "Home")</li>
Thanks
Yes, you can use AJAX. That is in case you don't want to load all partial views at once.
If it doesn't matter, you can just render them at once:
<div id="tabs-1">
#Html.Partial("GetClaim")
</div>
<div id="tabs-2">
#Html.Partial("GetProduct")
</div>
<div id="tabs-3">
#Html.Partial("GetClaim")
</div>
jQuery hides the elements that are not currently visible and will manage the switching automatically.
You can use an Ajax.ActionLink() - http://msdn.microsoft.com/en-us/library/dd493106.aspx
This will asynchronously submit your form to your controller method. If you set the AjaxOptions.InsertionMode to be AjaxOptions.InsertionMode.Replace then it will replace the partial view content with whatever you return from the controller. Then, you just need to return the GetContacts view in the creatcontacts controller action, as below:
[HttpGet]
public ActionResult GetContact()
{
return PartialView(RetrieveListOfContacts());
}
[HttpPost]
public ActionResult CreateContact(StronglyTypedContactModel contact)
{
if (ModelState.IsValid)
{
// .. write your contact here
return PartialView("GetContact", RetrieveListOfContacts());
}
else
{
return PartialView(contact);
}
}
EDIT
Also, you can specify that it be a GET request in the HttpMethod of the AjaxOptions, so as not to require form (as I originally assumed you did).

ASP.NET MVC 3 Adding comments in article view

I have article model with public ICollection<Comment> Comments { get; set; } and comment model. I have created view for article (Details view) and I want to show everything from model article (not problem) and comments to article to and after comments then show form for adding comment to article (not in other page, I want it in the view with article). For now I have this:
#model SkMoravanSvitavka.Models.Article
#{
ViewBag.Title = "Zobrazit";
}
<h2>Zobrazit</h2>
<fieldset>
<legend>Article</legend>
<div class="display-label">Title</div>
<div class="display-field">#Model.Title</div>
<div class="display-label">Text</div>
<div class="display-field">#Model.Text</div>
<div class="display-label">PublishedDate</div>
<div class="display-field">#String.Format("{0:g}", Model.PublishedDate)</div>
</fieldset>
#if (Model.Comments != null)
{
foreach (var comment in Model.Comments)
{
#Html.Partial("_Comment", comment)
}
}
<p>
#Html.ActionLink("Edit", "Edit", new { id = Model.ArticleID }) |
#Html.ActionLink("Back to List", "Index")
</p>
It shows article and there is partial view for all comments to article. And now I am not sure how to add form for adding comments. Thank you
Edit: Here is my comment controller and create methods (vytvorit = create in czech :) ):
public ActionResult Vytvorit(int articleID)
{
var newComment = new Comment();
newComment.articleID = articleID; // this will be sent from the ArticleDetails View, hold on :).
newComment.Date = DateTime.Now;
return View(newComment);
}
[HttpPost]
public ActionResult Vytvorit(Comment commentEntity)
{
db.Comments.Add(commentEntity);
db.SaveChanges();
return RedirectToAction("Zobrazit", "Clanek", new { id = commentEntity.articleID });
}
When I change #Html.RenderAction to #Html.Action it works. It is showing textbox for comment and I can add comment but there is problem that it not just add textbox but it add my site again (not just partial view but all view) and I am sure I add Create view for comment as partial.
Create a new Partial view, make it a strongly typed one of type Comment.
from the scaffolding templates, choose "Create" template.
handle the normal add new scenario of the comment.
add this Partial view to the Article details page.
Note that when you are about to save a new comment, you will need to get the hosting Article ID.
Hope it's now clear, if not, let me know.
update: assuming that you will add the "AddComment" partial view to your "Article details" view, you can do the following in order to add the comment.
1- Modify the GET (Create) action inside your CommentController as the following:
public ActionResult Create(int articleID)
{
var newComment = new CommentEntity();
newComment.articleID = articleID; // this will be sent from the ArticleDetails View, hold on :).
return View(newComment);
}
1- make the POST (Create) action like this:
[HttpPost]
public ActionResult Create(Comment commentEntity)
{
// Complete the rest..
}
2- The Partial view for the comment will look something like this:
#model NGO.Models.Comment
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<div class="addcommentbox">
<h2> Add Comment </h2>
#Html.TextAreaFor(model => model.Description)
<div class="ErrorMessage">
#Html.ValidationMessageFor(model => model.Description)
</div>
<input id="addComment" type="button" onclick="" value="Add" />
</div>
}
3- inside the ArticleDetails page, in the desired place that you need the add comment section to show, use RenderAction method to render the AddComment Partial view like the following:
Html.RenderAction("Create", "Comment",new {articleID = Model.ID});
the previous line will call the GET(Create) action inside CommentColtroller and pass the current Article ID, so the AddComment Partial view will come already populated with the current Article ID (and this is what we want).
that's it, feel free to ask me if it's not clear yet, and do let me know if it worked for you
I strongly recommend you to create view model for your article page. like below one;
public class ArticleViewModel {
public Article _article {get;set;}
//this is for the comment submit section
public Comment _comment {get;set;}
//this for the comments that you will view
public IQueryable<Comment> _comment {get;set;}
}
after that, pass this to your view from your controller and make your view strongly-typed to this ArticleViewModel class.
Create a section which is wrapped inside form tag as below;
#using(Html.BeginForm()){
#*Put your code inside here.
Create inputs for sending comments. like below;*#
#Html.TextboxFor(Model._comment.Content)
}
and then create a method for that;
[HttpPost]
[ActionName("name_of_your_article_page_action")]
public ActionResult Create(Comment commentEntity) {
}
NOTE : Of course, you do not need to create a seperate viewmodel. you can hardcode the name your inputs but this makes it hard to use validation and other kind of things. but not impossible to use validation though !

Where should I put this code?

Here's the code, written to be written in a controller:
CategoryRepository categoryRepo = new CategoryRepository();
var categories = categoryRepo.FindAllCategories();
ViewBag.Categories = categories;
Now I'd like to use this to create a nice list of Categories dynamically.
<div id="leftnavigationbar">
<ul>
#foreach (var category in ViewBag.Categories)
{
//Create li here.
}
<!-- ActionLink goes: Text, ActionName, Controller -->
<li>#Html.ActionLink("Libros", "Index", "Home")</li>
<li>#Html.ActionLink("Peliculas, Musica & Juegos", "Index", "Anuncios")</li>
<li>#Html.ActionLink("Computadoras", "Index", "Usuarios")</li>
<li>#Html.ActionLink("Bienes Raices", "Index", "Ayuda")</li>
<li>#Html.ActionLink("Bolsa de Trabajo", "Index", "Contacto")</li>
<li>#Html.ActionLink("Deportes y Fitness", "Index", "Contacto")</li>
<li>#Html.ActionLink("Electronicos y Celulares", "Index", "Contacto")</li>
</ul>
</div>
Right now I'm writing this code to the _Layout.cshtml file. But I'd like to know where to write this so it runs always, sort of like a MasterPage.
Any suggestions?
Edit:
It appears that my initial intent isn't possible.
#foreach (var category in ViewBag.Categories)
{
<li>#Html.ActionLink(category.Name, "Index", "Home")</li>
}
Any suggestions on how accomplish what I'm trying to do? Just pull a list of categories and render them using a foreach loop. Then have it placed somewhere so it's viewable on all pages.
As always you start by creating a view model:
public class CategoryViewModel
{
public string CategoryName { get; set; }
}
Then in your controller you fill the view model:
public ActionResult Index()
{
var categories = categoryRepo.FindAllCategories();
var model = MapModelToViewModel(categories);
return View(model);
}
And finally your strongly typed view could use a display template. Obviously the view will be strongly typed to IEnumerable
<ul>
#Html.EditorForModel()
<!-- ActionLink goes: Text, ActionName, Controller -->
<li>#Html.ActionLink("Libros", "Index", "Home")</li>
...
</ul>
And your display template (~/Views/Home/DisplayTemplates/CategoryViewModel.cshtml):
#model YourApp.Models.CategoryViewModel
<li>#Model.CategoryName</li>
As you can see with strongly typed views and display templates you don't even need to write loops in your views.
As an alternative to display templates you could use Html.Action or Html.RenderAction helers. Phil Haack wrote a nice blog post about them. I suspect that you were forced to use the ugly untyped ViewBag because this code is situated in your master template and you don't have a view model. No problem, with Html.Action you could have a specific controller that will do this:
public class CategoriesController: Controller
{
public ActionResult Index()
{
var categories = categoryRepo.FindAllCategories();
var model = MapModelToViewModel(categories);
return View(model);
}
}
And then have a corresponding partial view which will take care of rendering the categories (~/Views/Categories/Index.cshtml):
#model IEnumerable<YourApp.Models.CategoryViewModel>
#Html.DisplayForModel()
And finally use the same display template.
Now in your master page you could simply include this child action:
<ul>
#Html.Action("index", "categories")
<!-- ActionLink goes: Text, ActionName, Controller -->
<li>#Html.ActionLink("Libros", "Index", "Home")</li>
...
</ul>
You're looking for something called a 'partial view'.

Resources