I have the following code that was generated using scaffolding and IDJefe is an int in my database, but I want the end users to choose a name from a comboBox.
How could I accomplish this?
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SeguimientoDocente.Area>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
UTEPSA | Editando Area
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Editando Area: <%: Model.Nombre %></h2>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Informacion Detallada de Area | <%: Model.Nombre %></legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.Nombre) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Nombre) %>
<%: Html.ValidationMessageFor(model => model.Nombre) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.IDJefe) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.IDJefe) %>
<%: Html.ValidationMessageFor(model => model.IDJefe) %>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Volver a Listado General", "Index") %>
</div>
</asp:Content>
I've tried the following to no avail.
<%: Html.DropDownList(Model.Jefes???? %>
I could do something like this, but creating a new object for a simple thing like this seems a waste.
public ActionResult Edit(int id)
{
Area area = areaRepository.GetArea(id);
JefeRepository jefe = new JefeRepository();
ViewData["Jefes"] = new SelectList(jefe.FindAllJefes(), area.Jefe.Nombre);
return View(area);
}
Is there a better way?
You could take a look at Editor Templates. Here is an example that sounds similar to what you want to do:
http://blogs.msdn.com/b/nunos/archive/2010/02/08/quick-tips-about-asp-net-mvc-editor-templates.aspx
Edit:
It involves creating a partial view and then using Data Annotations to call that view:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<%= Html.DropDownList("",new SelectList((string[]) ViewData["Ratings"],Model)) %>
Related
How do I create a view to add a new item to a list in a view model?
So I have view model with a list of objects in it (view model also has 1 other object in it). Basically the list will be comments (so I may have zero to x number of comments).
I am using VS 2010 (and I don't think it is the razor view engine?)
Here is my view, I want to have the option to add a new item to the list
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<JPROCommunitydataListings.ViewModels.dataWithCommentsViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
data Solution
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<p>data Description# <%: Model.data.Description %></p>
<p>data ParameterID# <%: Model.data.ParameterID %></p>
<%--<h2>dataWithComments</h2>--%>
<table class="table table-striped table-hover">
<tr>
<th>
Comment
</th>
</tr>
<% foreach (var Comment in Model.Comments) { %>
<td>
<%: Comment.comment1%>
</td>
<% } %>
</table>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Add Comment</legend>
<div class="editor-label">
<"label">
What to do here????????
<%--<%: Html.LabelFor(model => model.Comments[0].comment1) %>--%>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Comments.comment1)%>
<%: Html.ValidationMessageFor(model => model.Comments[0].comment1)%>
</div>
What to do here????????
<p>
<input type="submit" value="Search" />
</p>
</fieldset>
<% } %>
</fieldset>
<p>
<%: Html.ActionLink("Search", "Search") %>
</p>
</asp:Content>
"What to do here"
You need a form:
<form action="/ControlerName/AddComment" method="POST">
...
<%: Html.TextBox("CommentToAdd")%>
<%: Html.Hidden("PostIdToAddComment")%>
<input type="submit" value="Search" />
</form>
In controller you save your comment to DB, then redirect back to the original action that will display the page, and so the comment should show up assuming you are querying the database for all comments:
[HttpPost]
public ActionResult AddComment(string commentToAdd, int postIdToAddComment)
{
//do your database stuff here to add comment
return RedirectToAction("DataWithCommentsOrWhateverTheNameOfTheActionIsForTheOriginalPage")
}
I'm trying to create a create model object page. I'm using asp.net mvc with c#. In my project i'm trying to create a library application which has books and we can add book from application which has picture. So my Create Controller like this,
[HttpPost]
public ActionResult Create([Bind(Exclude = "id,bringBack,borrower,isBorrowed")]Book bookToCreate, HttpPostedFileBase picture1)
{
try
{
if (picture1.ContentLength > 0)
{
var fileName = Path.GetFileName(picture1.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/pictures"), fileName);
picture1.SaveAs(path);
}
// TODO: Add insert logic here
_entities.AddToLibrary(bookToCreate);
_entities.SaveChanges();
return RedirectToAction("ListBooks");
}
catch
{
return View();
}
}
and my view is like this,
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MvcApplication2.Models.Book>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Create</title>
</head>
<body>
<% using (Html.BeginForm(new { enctype = "multipart/form-data" }))
{%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.name) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.name) %>
<%: Html.ValidationMessageFor(model => model.name) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.author) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.author) %>
<%: Html.ValidationMessageFor(model => model.author) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.picture) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.picture) %>
<%: Html.ValidationMessageFor(model => model.picture) %>
</div>
<input type='file' name='picture1' id='picture1' />
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
I have tried many things but i couldn't upload any file. What can i do?
Try getting the posted file(s) from the Request instead.
var picture1 = this.Request.Files["picture1"];
In your Book model should be a preperty
HttpPostedFileBase picture1
I'm having trouble with one particular issue, I was hoping someone could help me out.
I've completed the MVC Music Store tutorial, and now I'm trying to add some administrator functionality - practice as I will have to do this in an MVC application in my job. The application is using the aspnet membership api, and what I have done so far is created a view to list the users.
What I want to be able to do, is click on the users name in order to change their password. To try and carry the username to the changeUserPassword controller (custom made). I registered a new route in the global.asax.cs file in order to display the username in the URL, which is working so far.
UserList View
<%: Html.RouteLink(user.UserName, "AdminPassword", new { controller="StoreManager", action="changeUserPassword", username = user.UserName }) %>
Global.asax.cs
routes.MapRoute(
"AdminPassword", //Route name
"{controller}/{action}/{username}", //URL with parameters
new { controller = "StoreManager", action = "changeUserPassword", username = UrlParameter.Optional}
);
So now the URL looks like this when I reach the changeUserPassword view:
http://localhost:51236/StoreManager/changeUserPassword/Administrator
Here is the GET changeUserPassword action:
public ActionResult changeUserPassword(string username)
{
ViewData["username"] = username;
return View();
}
I wanted to store the username in ViewData as I would like to use it in the GET changeUserPassword for display purposes, and also as a hidden value in the form. This is in order to pass it through to enable me to reset the password.
Having debugged through the code, it seems that 'username' is null.
How can I get this to work so that the username carries over from the Html.RouteLink, to the changeUserPassword action?
Any help would be appreciated :)
Here is my complete code:
UserList.aspx
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<System.Web.Security.MembershipUserCollection>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
UserList
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>UserList</h2>
<table>
<tr>
<th>User Name</th>
<th>Last Activity date</th>
<th>Locked Out</th>
</tr>
<%foreach (MembershipUser user in Model){ %>
<tr>
<td><%: Html.RouteLink(user.UserName, "AdminPassword", new { controller="StoreManager", action="changeUserPassword", username = user.UserName }) %></td>
<td><%: user.LastActivityDate %></td>
<td><%: user.IsLockedOut %></td>
</tr>
<% }%>
</table>
</asp:Content>
changeUserPassword.aspx
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<musicStoreMVC.ViewModels.ResetPasswordAdmin>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
changeUserPassword
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Change Password: <%: ViewData["username"] %></h2>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.Hidden("username",ViewData["username"]) %>
<%: Html.LabelFor(model => model.password) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.password) %>
<%: Html.ValidationMessageFor(model => model.password) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.confirmPassword) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.confirmPassword) %>
<%: Html.ValidationMessageFor(model => model.confirmPassword) %>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
<% } %>
<div>
<%: Html.ActionLink("Back to List", "Index") %>
</div>
</asp:Content>
My actions
public ActionResult UserList()
{
var users = Membership.GetAllUsers();
return View(users);
}
public ActionResult changeUserPassword(string username)
{
ViewData["username"] = username;
return View();
}
Something must be going wrong with your routes.
If you navigate to this URL, and set a breakpoint in the changeUserPassword action method - you'll probable see the username value correctly:
http://localhost:51236/StoreManager/changeUserPassword?username=Administrator
How do I debug code in the View in asp.net mvc2 application?
Edit after progress last night:
Ok so now I have the following:
in Shared\EditorTemplates\Equipment.ascx :
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<DAT.Models.Item>" %>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<div class="editor-label">
<%: Html.Label("Item ID") %>
<%: Html.TextBoxFor(model => model.ItemID) %>
<%: Html.ValidationMessageFor(model => model.ItemID) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.ModelID) %>
<%: Html.DropDownListFor(x => x.Model.Model1, new SelectList(Model.Model.Model1, "ModelId", "Model", Model.ModelID)) %>
<%: Html.ValidationMessageFor(model => model.ModelID) %>
</div>
...
in Item\Edit.aspx :
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<DAT.ViewModels.ItemEditViewModel>" %>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<%: Html.EditorFor(model => model.Item) %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
The controller:
public ActionResult Edit(int id)
{
var models = from p in database.Models.Where(x => x.Model1 != null) select p;
var viewModel = new ViewModel
{
Things = database.Things.Single(a => a.ItemID == id),
//tried this:
//Models = database.Models
Models = models
};
return View(viewModel);
}
So I am sure that the problem is with this line
<%: Html.DropDownListFor(x => x.Model.Model1, new SelectList(Model.Model.Model1, "ModelId", "Model", Model.ModelID)) %>
When generating the selectlist, I don't have IEnumerable for the first parameter? Or one of the values I am feeding this is causing null. How do I get the list of models in my view?
EDIT AFTER PULLING ALL MY HAIR OUT:
It seems the problem lies in this example: http://www.asp.net/mvc/tutorials/mvc-music-store-part-4 . Strangely, I am not sure if it is following best practice. Look at the code and how they pass the models about - it seems stupidly obscure using ViewData["Blah"] and the Models as well, why can't you just have it all sent as the model? Look at the code how they have done it:
Album.ascx :
<%# Import Namespace="MvcMusicStore"%>
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcMusicStore.Models.Album>" %>
<script src="/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcAjax.js" type="text/javascript"></script>
<script src="/Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>
<p>
<%: Html.LabelFor(model => model.Title)%>
<%: Html.TextBoxFor(model => model.Title)%>
<%: Html.ValidationMessageFor(model => model.Title)%>
</p>
<p>
<%: Html.LabelFor(model => model.Price)%>
<%: Html.TextBoxFor(model => model.Price)%>
<%: Html.ValidationMessageFor(model => model.Price)%>
</p>
<p>
<%: Html.LabelFor(model => model.AlbumArtUrl)%>
<%: Html.TextBoxFor(model => model.AlbumArtUrl)%>
<%: Html.ValidationMessageFor(model => model.AlbumArtUrl)%>
</p>
<p>
<%: Html.LabelFor(model => model.Artist)%>
<%: Html.DropDownList("ArtistId", new SelectList(ViewData["Artists"] as IEnumerable, "ArtistId", "Name", Model.ArtistId))%>
</p>
<p>
<%: Html.LabelFor(model => model.Genre)%>
<%: Html.DropDownList("GenreId", new SelectList(ViewData["Genres"] as IEnumerable, "GenreId", "Name", Model.GenreId))%>
</p>
View:
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcMusicStore.ViewModels.StoreManagerViewModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Edit - <%: Model.Album.Title %>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Edit Album</h2>
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Edit Album</legend>
<%: Html.EditorFor(model => model.Album, new { Artists = Model.Artists, Genres = Model.Genres}) %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
<div>
<%:Html.ActionLink("Back to Albums", "Index") %>
</div>
</asp:Content>
View Model:
using System.Collections.Generic;
using MvcMusicStore.Models;
namespace MvcMusicStore.ViewModels
{
public class StoreManagerViewModel
{
public Album Album { get; set; }
public List<Artist> Artists { get; set; }
public List<Genre> Genres { get; set; }
}
}
And the controller:
//
// GET: /StoreManager/Edit/5
public ActionResult Edit(int id)
{
var viewModel = new StoreManagerViewModel
{
Album = storeDB.Albums.Single(a => a.AlbumId == id),
Genres = storeDB.Genres.ToList(),
Artists = storeDB.Artists.ToList()
};
return View(viewModel);
}
So it looks to me like the model is built in the controller as makes logical sense to me. Then in the view they use this statement which causes my confusion:
<%: Html.EditorFor(model => model.Album, new { Artists = Model.Artists, Genres = Model.Genres}) %>
The model is being split/changed and now we send the other (Artists, Genres) as ViewData ??
Can someone explain, and is this at all fitting with the entire design pattern?
You could put a breakpoint in your controller action and analyze your model and view data.
This being said, why are you using a strongly typed view and ViewData at the same time? Make sure that ViewData["Models"] as IEnumerable is not null (in your controller) or even better get rid of it and put it in your model as a strongly typed property. Also I would recommend you using the strongly typed helper DropDownListFor:
<%: Html.DropDownListFor(
x => x.ModelID,
new SelectList(Model.Models, "ModelId", "Model", Model.ModelID)
)%>
I have got an Entity model which contains a collection of Message objects which are of the type Message which has several properties, including content, MessageID, from, and to.
I have created an EditorTemplate for type Message, however, I cannot get it to display the contents of the Messages collection.
There are no errors, but nothing is output.
Please note that the view code is from an EditorTemplate for the parent Talkback class. Can you have an EditorTemplate calling another EditorTemplate for a child collection?
Both the Talkback and Message class are generated by Entity framework from an existing database.
View code:
<% foreach (TalkbackEntityTest.Message msg in Model.Messages)
{
Html.EditorFor(x=> msg, "Message");
} %>
This is my template code. It is the standard auto-generated view code with some minor changes.
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<TalkbackEntityTest.Message>" %>
<%: Html.ValidationSummary(true) %>
<fieldset>
<legend>Fields</legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.MessageID) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.MessageID) %>
<%: Html.ValidationMessageFor(model => model.MessageID) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.acad_period) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.acad_period) %>
<%: Html.ValidationMessageFor(model => model.acad_period) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.talkback_id) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.talkback_id) %>
<%: Html.ValidationMessageFor(model => model.talkback_id) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.From) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.From) %>
<%: Html.ValidationMessageFor(model => model.From) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.To) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.To) %>
<%: Html.ValidationMessageFor(model => model.To) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.SentDatetime) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.SentDatetime, String.Format("{0:g}", Model.SentDatetime)) %>
<%: Html.ValidationMessageFor(model => model.SentDatetime) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.content) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.content) %>
<%: Html.ValidationMessageFor(model => model.content) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.MessageTypeID) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.MessageTypeID) %>
<%: Html.ValidationMessageFor(model => model.MessageTypeID) %>
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
There is definitely content in the Message collection as, if I remove EditorFor and put in response.write on the content property of the Message class, I get the content field for 3 Message objects on the page, which is exactly as expected.
You don't need to foreach manually. Just put a file called Message.ascx containing the editor template you've shown inside the ~/Shared/EditorTemplates/ folder and in your view just include it:
<%: Html.EditorFor(model => model.Messages) %>