I am entirely new to asp.net mvc and this is my first sample project that I need to show one textbox in one view when the user entered a value in that textbox, I need to display that value in label in another view.
for that I have done like this ..
this is my controller class
public class TextBoxController : Controller
{
//
// GET: /TextBox/
public ActionResult Index()
{
return View();
}
}
and this is my model class
namespace MvcTestApplication.Models
{
public class TextboxModel
{
[Required]
[Display(Name= "Textbox1")]
public string EnteredValue { get; set; }
}
}
and this is my view
#model MvcTestApplication.Models.TextboxModel
#{
ViewBag.Title = "TextboxView";
}
<h2>TextboxView</h2>
#using (Html.BeginForm())
{
<div>
<fieldset>
<legend>Enter Textbox Value</legend>
<div class ="editor-label">
#Html.LabelFor(m => m.EnteredValue)
</div>
<div class="editor-field">
#Html.TextBoxFor(m=>m.EnteredValue)
</div>
<p>
<input type="submit" value="Submit Value" />
</p>
</fieldset>
</div>
}
I am not able to see any textbox and any button on page and I am getting error like
HTTP:404 : Resource Cannot be found
I am using visual studio 2012 and mvc4..
would any pls suggest any idea on this one ..
Many thanks..
RE-WRITTEN
In simple terms, to access a page on ASP.NET MVC, you should point the URL to its controller name. In this case, TextBox:
localhost:2234/TextBox/TextBox
Also, you forgot to add an ActionResult for this new view. When you're loading the page, it's going through the Index one, which is empty.
The final code should look like this:
Controller
public class TextBoxController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult TextBox(MvcApplication1.Models.TextBoxModel model)
{
return View(model);
}
}
Model
public class TextBoxModel
{
[Required]
[Display(Name = "Textbox1")]
public string EnteredValue { get; set; }
}
Razor View (Index)
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
Razor View (TextBox)
#model MvcApplication1.Models.TextBoxModel
#{
ViewBag.Title = "TextBox";
}
<h2>TextBox</h2>
#using (Html.BeginForm())
{
<div>
<fieldset>
<legend>Enter Textbox Value</legend>
<div class ="editor-label">
#Html.LabelFor(m => m.EnteredValue)
</div>
<div class="editor-field">
#Html.TextBoxFor(m=>m.EnteredValue)
</div>
<p>
<input type="submit" value="Submit Value" />
</p>
</fieldset>
</div>
}
Make sure that you have registered the URL via route config.
Find more about asp.net routing here
UPDATE:
Make sure that file name of your view is Index.cshtml since your controller doesn't specify any return view names.
Related
I am trying to pass hidden field value from view to controller by doing the following
#Html.HiddenFor(model => model.Articles.ArticleId)
and also tried
<input type="hidden" id="ArticleId" name="ArticleId" value="#Model.Articles.ArticleId" />
On both instances the value of ArticleId is 0 but when i use TextboxFor i can see the correct ArticleId, please help
Here it is
View
#model ArticlesCommentsViewModel
....
#using (Html.BeginForm("Create", "Comments", FormMethod.Post))
{
<div class="row">
<div class="col-xs-10 col-md-10 col-sm-10">
<div class="form-group">
#Html.LabelFor(model => model.Comments.Comment, new { #class = "control-label" })
#Html.TextAreaFor(m => m.Comments.Comment, new { #class = "ckeditor" })
#Html.ValidationMessageFor(m => m.Comments.Comment, null, new { #class = "text-danger"})
</div>
</div>
</div>
<div class="row">
#*#Html.HiddenFor(model => model.Articles.ArticleId)*#
<input type="hidden" id="ArticleId" name="ArticleId" value="#Model.Articles.ArticleId" />
</div>
<div class="row">
<div class="col-xs-4 col-md-4 col-sm-4">
<div class="form-group">
<input type="submit" value="Post Comment" class="btn btn-primary" />
</div>
</div>
</div>
}
Controller
// POST: Comments/Create
[HttpPost]
public ActionResult Create(CommentsViewModel comments)//, int ArticleId)
{
var comment = new Comments
{
Comment = Server.HtmlEncode(comments.Comment),
ArticleId = comments.ArticleId,
CommentByUserId = User.Identity.GetUserId()
};
}
Model
public class CommentsViewModel
{
[Required(ErrorMessage = "Comment is required")]
[DataType(DataType.MultilineText)]
[Display(Name = "Comment")]
[AllowHtml]
public string Comment { get; set; }
public int ArticleId { get; set; }
}
ViewModel
public class ArticlesCommentsViewModel
{
public Articles Articles { get; set; }
public CommentsViewModel Comments { get; set; }
}
The model in the view is ArticlesCommentsViewModel so therefore the parameter in your POST method must match. Your use of
#Html.HiddenFor(model => model.Articles.ArticleId)
is correct, but you need to change the method to
[HttpPost]
public ActionResult Create(ArticlesCommentsViewModel model)
and the model will be correctly bound.
As a side note, your ArticlesCommentsViewModel should not contain data models, and instead should contain only those properties you need in the view. If typeof Articles contains properties with validation attributes, ModelState would be invalid because your not posting all properties of Article.
However, since CommentsViewModel already contains a property for ArticleId, then you could just use
#Html.HiddenFor(model => model.Comments.ArticleId)
and in the POST method
[HttpPost]
public ActionResult Create([Bind(Prefix="Comments")]CommentsViewModel model)
to effectively strip the "Comments" prefix
In your controller, you need to pass the hidden value with the model,
for example, if you have a userId as a hidden value, in your Page you add:
#Html.HiddenFor(x => x.UserId)
In your model of course you would already have UserId as well.
In your controller, you need the model as a parameter.
public async Task<ActionResult> ControllerMethod(YourViewmodel model) { model.UserId //this should be your HiddenValue
I guess your model have another class called Articles inside CommentsViewModel.Change your controller function for accessing the ArticleId accordingly.
[HttpPost]
public ActionResult Create(CommentsViewModel comments)//, int ArticleId)
{
var comment = new Comments
{
Comment = Server.HtmlEncode(comments.Comment),
ArticleId = comments.Articles.ArticleId, // Since you are using model.Articles.ArticleId in view
CommentByUserId = User.Identity.GetUserId()
};
}
In my case, I didn't put the hidden input in the form section, but out of form, so it's not send to backend. Make sure put hidden input inside the form.
Also make sure name attribute is specified on the hidden field. Element's "id" is often used on client side but "name" on server side.
<input type="hidden" value="#ViewBag.selectedTraining" id="selectedTraining"
name="selectedTraining" />
In my case, I was passing a couple of fields back and forth between controllers and views. So I made use of hidden fields in the views.
Here's part of the view. Note a controller had set "selectedTraining" and "selectedTrainingType" in the ViewBag to pass to the view. So I want these values available to pass on to a controller. On the hidden tag, the critical thing is set to the "name" attribute. "id" won't do it for you.
#using (Html.BeginForm("Index", "ComplianceDashboard"))
{
<input type="hidden" value="#ViewBag.selectedTraining" id="selectedTraining" name="selectedTraining" />
<input type="hidden" value="#ViewBag.selectedTrainingType" id="selectedTrainingType" name="selectedTrainingType" />
if (System.Web.HttpContext.Current.Session["Dashboard"] != null)
{
// Show Export to Excel button only if there are search results
<input type="submit" id="toexcel" name="btnExcel" value="Export To Excel" class="fright" />
}
<div id="mainDiv" class="table">
#Html.Grid(Model).Columns(columns =>
Then back on the controller:
// POST: Dashboard (Index)
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(string excel)
{
string selectedTraining, selectedTrainingType;
selectedTraining = Request["selectedTraining"];
selectedTrainingType = Request["selectedTrainingType"];
Or can put the requests as parameters to the method: public ActionResult Index(string excel, string selectedTraining, string selectedTrainingType)
While attempting access/use the default editor templates in MVC5.
I receive the error:
The model item passed into the dictionary is of type 'System.String',
but this dictionary requires a model item of type
'MvcContrib.UI.InputBuilder.Views.PropertyViewModel`1[System.Object]'.
Why is this happening?
Some background:
My model (TestModel.cs):
namespace MyTest.Web.Controllers.Models
{
public class TestModel
{
public TestModel()
{
Name = "Fred";
}
public string Name { get; set; }
}
}
My Controller (MyTestController.cs):
namespace MyTest.Web.Controllers
{
public class MyTestController : Controller
{
[HttpGet]
public ActionResult Index()
{
TestModel testData = new TestModel();
return View(testData);
}
...
}
}
My View (Index.cshtml):
#model MyTest.Web.Controllers.Models.TestModel
#{
ViewBag.Title = "MyTest";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="mainDisplay">
<h2>Test</h2>
<div>
#using (Html.BeginForm("ProcessResults", "MyTest", FormMethod.Post))
{
<div style="display:block;">
<div style="display:inline;">Name:</div>
<div style="display:inline;">#Html.EditorFor(x => x.Name)</div>
</div>
<div style="display:block;">
<input type="submit" name="Submit" value="Submit" />
</div>
}
</div>
</div>
The error occurs on the following line
<div style="display:inline;">#Html.EditorFor(x => x.Name)</div>
and the view will not render
Things I have tried:
The sample from "ASP.NET MVC Basics Part 1: View Model binding" and this sample works without a problem.
If I add a custom editor template under ~/Views/Shared/EditorTemplates/Name.cshtml and I invoke #Html.EditorFor(x => x.Name, "Name") then the page renders
If I change the code to be #Html.TextBoxFor(x => x.Name, "Name") then the page renders
Finally, the solution has System.Web.Mvc assembly (which should contain the default editor templates).
What am I missing?
I am new to asp.net MVC. I have a dynamic table in my project. Adding dynamic rows in table is achieved with the help of following link
Adding and deleting rows in dynamic table in Asp.net mvc razor view
I need to edit and update the dynamic table.
I have tried following code
My sample model
public class Gift
{
public string Name { get; set; }
public double Price { get; set; }
}
public class GiftViewModel
{
public string Age { get; set; }
public DateTime TheDate { get; set; }
public IEnumerable<Gift> Gifts { get; set; }
}
My sample Controller
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(GiftViewModel model)
{
// do work here
return RedirectToAction("Index");
}
public ViewResult AddNew()
{
return View("_TimeSheetView");
}
}
My sample Partial View
#model HelloWorldMvcApp.Gift
#using (Html.BeginCollectionItem("giftList"))
{
<div>
<span class="drop_medium">
#Html.TextBoxFor(m => m.Name)
</span>
<span class = "drop_medium">
#Html.TextBoxFor(m => m.Price)
</span>
</div>
}
My sample main view
#model HelloWorldMvcApp.GiftViewModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.Age)
#foreach (var data in Model.Gifts)
{
{ Html.RenderPartial("_TimeSheetView", data); }
}
#Html.ActionLink("Add another", "AddNew", null, new { id="addItem" })
<input type="submit" value="Save"/>
}
<script type="text/javascript">
$("#addItem").click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) { $("#dynamic").append(html); }
});
return false;
});
</script>
When I click 'Add Another' button a row is added to the table. After editing the values in the table When I click submit button I receive nothing in the controller. The IEnumerable Gifts variable is null. How to take the table values to the controller. Please help me to fix this is issue. Thanks in advance
Your model's collection property is named Gifts so the partial needs to be
#model HelloWorldMvcApp.Gift
#using (Html.BeginCollectionItem("Gifts")) // not "giftlist"
{
...
}
This will generate inputs with the correct name attributes for binding to a collection (where ## is a Guid)
<input name="Gifts[##].Name" ... />
<input name="Gifts[##].Price" ... />
<input type="hidden" name="Gifts.Index" value="##" />
The problem you're facing is the name of the rendered input isnt matching your model structure. There are a couple of ways out of this:
Make an editor template for the model type
your partial view:
#model IEnumerable<HelloWorldMvcApp.Gift>
#Html.EditorForModel("","Gifts")
and an EditorTemplate for the Gift model:
#model HelloWorldMvcApp.Gift
<div>
<span class="drop_medium">
#Html.TextBoxFor(m => m.Name)
</span>
<span class = "drop_medium">
#Html.TextBoxFor(m => m.Price)
</span>
</div>
Manually create the inputs with the properly parsed name - "Gifts[x].Property"
Obviously the first option is far cleaner and imho preferred.
Hope this works, and helps :)
I am trying to pass a string variable inside asp.net MVC. I use breakpoints so I see that it does go to the correct method in the controller, but the variables posted are equal to null.
My markup:
#{
ViewBag.Title = "TestForm";
}
<h2>TestForm</h2>
#using (Html.BeginForm()) {
<input type="text" id="testinput" />
<input type="submit" value="TestForm" />
}
My controller:
public ActionResult TestForm()
{
return View();
}
[HttpPost]
public ActionResult TestForm(string testinput)
{
Response.Write("[" + testinput + "]");
return View();
}
I put the breakpoint inside the second TestForm method and testinput is null....
Am I missing something?
Note: I realize that most of the time I will be using the model to pass data around, but I would like to know that I can pass strings as well.
As part of the same question, how do I pass several variables? Would the method in my controller look like this:
[HttpPost]
public ActionResult TestForm(string var1, var2)
{
}
For me it looks like that you set the id not the name. I use MVC3 every day, so i dont reproduce your sample. (I am awake for 20 hours programming ;) but still motivated to help ) Please tell me if it dont work. But for me it looks like you have to set the "name" property ... not the id property. Try that ... i am waiting right now to help you if it does not work.
<input type="text" id="testinput" name="testinput" />
On a slightly separate note there is nothing wrong with passing variables like you are, but a more efficient way would be to pass around a strongly typed view model allowing you to take advantage of many aspects of MVC's goodness:
strongly-typed views
MVC Model Binding
Html Helpers
Create a new view model:
public class TestModel
{
public string TestInput { get; set; }
}
Your test controller:
[HttpGet]
public ActionResult TestForm()
{
return View();
}
[HttpPost]
public ActionResult TestForm(FormCollection collection)
{
var model = new TestModel();
TryUpdateModel(model, collection);
Response.Write("[" + model.TestInput + "]");
return View();
}
Your view:
#model <yourproject>.Models.TestModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>TestForm</title>
</head>
<body>
<div>
#using(Html.BeginForm())
{
<div class="editor-label">
#Html.LabelFor(m => m.TestInput)
</div>
<div class="editor-label">
#Html.TextBoxFor(m => m.TestInput)
</div>
<input type="submit" value="Test Form"/>
}
</div>
</body>
</html>
(Again, an MVC validation question. I know, I know...)
I'd like to use AutoMapper (http://automapper.codeplex.com/) to validate fields in my Create Views for fields that are not in my database (and thus not in my DataModel).
Example: I have an Account/Create View for users to create a new account and I want both a Password and ConfirmPassword field so users have to enter their password twice for confirmation.
The Account table in the database looks like this:
Account[Id(PK), Name, Password, Email]
I've generated an ADO.NET Entity Data Model and from that, I generated the Models using an ADO.NET Self-Tracking Entity Generator.
I've also written a custom AccountViewModel for validation annotations like [Required].
So, to summarize, this is my project structure:
Controllers:
AccountController
Models:
Database.edmx (auto-generated from database)
Model.Context.tt (auto-generated from edmx)
Model.tt (auto-generated from edmx)
AccountViewModel.cs
Views:
Account
Create.cshtml
The code of my AccountViewModel looks like this:
public class AccountViewModel
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Password { get; set; }
[Required]
[Compare("Password")]
public string ConfirmPassword { get; set; }
}
Now, my Create View looks like this:
#model AutoMapperTest.Models.Account
<script src="#Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Account</legend>
<div class="editor-label">
Name
</div>
<div class="editor-field">
#Html.TextBox("Name")
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
Email
</div>
<div class="editor-field">
#Html.TextBox("Email")
#Html.ValidationMessageFor(model => model.Email)
</div>
<div class="editor-label">
Password
</div>
<div class="editor-field">
#Html.TextBox("Password")
#Html.ValidationMessageFor(model => model.Password)
</div>
<div class="editor-label">
Confirm your password
</div>
<div class="editor-field">
#Html.TextBox("ConfirmPassword");
#Html.ValidationMessageFor(model => model.ConfirmPassword)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
My code fails because my Model does not contain the ConfirmPassword field of course.
Now, a little bird whispered to me the AutoMapper could fix that for me. But I can't figure it out... Can someone please tell me what I have to do to make this work? My AccountController looks like this now:
private readonly AccountViewModel _viewModel = new AccountViewModel();
private readonly DatabaseEntities _database = new DatabaseEntities();
//
// GET: /Account/Create
public ActionResult Create()
{
Mapper.CreateMap<AccountViewModel, Account>();
return View("Create", _viewModel);
}
//
// POST: /Account/Create
[HttpPost]
public ActionResult Create(AccountViewModel accountToCreate)
{
try
{
if (ModelState.IsValid)
{
var newAccount = new Account();
Mapper.Map(accountToCreate, newAccount);
_database.Account.AddObject(newAccount);
_database.SaveChanges();
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
But this doesn't work... (Got the example from http://weblogs.asp.net/shijuvarghese/archive/2010/02/01/view-model-pattern-and-automapper-in-asp-net-mvc-applications.aspx)
Can anyone please enlighten me on this matter? Thank you very much, and my apologies for the wall of text and the hundreds of questions about the same subject...
Few remarks about your code:
Your view is strongly typed (#model declaration) to the Account model whereas it should be typed to the AccountViewModel view model (there is no point in declaring a view model if you don't use it in the view).
AutoMapper is not used for validation, only for converting between types
You don't need to declare a readonly field for your view model (AccountViewModel) inside the controller. You could instantiate the view model inside the GET action and leave the default model binder instantiate it as action argument for the POST action.
You should do the AutoMapper configuration (Mapper.CreateMap<TSource, TDest>) only once for the entire application (ideally in Application_Start) and not inside a controller action
There is no Email field on your view model which might be the reason for the update to fail (especially if this field is required in your database)
So here's how your code might look like:
public ActionResult Create()
{
var model = new AccountViewModel();
return View("Create", model);
}
[HttpPost]
public ActionResult Create(AccountViewModel accountToCreate)
{
try
{
if (ModelState.IsValid)
{
var newAccount = Mapper.Map<AccountViewModel, Account>(accountToCreate);
_database.Account.AddObject(newAccount);
_database.SaveChanges();
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
replace the first line of you view with
#model AutoMapperTest.AccountViewModel
Also you only need to call Mapper.CreateMap once for app lifetime (e.g. at app start)