asp.net view syntax and html helper - c#

This is actually two questions in one.
First question is about the following:
<div class="form-group">
#Html.LabelFor(model => model.xxx, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.xxx , new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.xxx, "", new { #class = "text-danger" })
</div>
</div>
I don't understand what model => model.xxx means, I know what it's doing but i don't know how to interpret the syntax.
the second question is, if I have - for example -
foreach (var item in Model)
how can I replace
#Html.EditorFor(model => model.xxx , new { htmlAttributes = new { #class = "form-control" } })
with
#Html.EditorFor(item.stringProperty , new { htmlAttributes = new { #class = "form-control" } })
when I try this, it gives me errors, is there an overloaded EditorFor helper that accepts this?
thank you!

One view can has 0 or 1 Model, which's sending from controller.
public class Person
{
public string Name {get;set;}
public int Age {get;set;}
}
public ViewResult Index()
{
Person p = new Person() { Name = "P1", Age = 100};
return View(p);//
}
if your View's name "Index" then you can use second way for View, which contain 2 parameters:
ViewName and model
return View("Index", model: p);
then in your View you can use the model, if it has been implemented that:
#model Person//and remember about namespace
#
{
...
}
#using(Html.BeginForm("ActionName", "controllerName", FormMethod.Post))
{
#Html.EditorFor(model => model.Name); // it create input, check in F12 in your browse - then you can exactly understand.
}
if you want create Editor for item you must use:
#Html.TextBox("YourName")
for example:
#using(Html.BeginForm("Action", "controller")
{
#Html.TextBox("YourName")
<input type="submit" value="ok"/>
}
and in your controllerController:
public ViewResult Action(string YourName)
{
//here you got value for string YourName
return View();
}
and helpfully answer's here:
ASP.NET MVC get textbox input value
Edit, answer about exactly problem (which containt in comment below question):
I have a list, and I want to display an input text box for each item in the list, but I want each text box to have text inside when its created, text from each item in the list (coming from the item's property)
#foreach(var item in Model)
#using(Html.BeginForm("MyMethod", "Controller"))
{
#Html.TextBox("item", item)
<input type="submit" value="ok" />
}
and in your controller add MyMethod:
[HttpPost]
public ViewResult MyMethod(string item)
{
...
}
or
[HttpPost]
public ViewResult MyMethod(int item) //if it's an int
{
...
}
and if you want to have a better security page please read about Html.AntiForgeryToken:
http://msdn.microsoft.com/en-us/library/dd470175(v=vs.118).aspx
#using(Html...())
{
#Html.AntiForgeryToken()
(...)
}

I see you already got the answer of your first question.
For the second one, i think
#Html.EditorFor(item => item.stringProperty , new { htmlAttributes = new { #class = "form-control" } })
will work fine

Related

Passing selected string from dropdown to controller

I am displaying a dropdown list from my controller as follows:
public ActionResult Index()
{
var title = new List<String>()
{
"English", "French", "Spanish"
};
List<SelectListItem> languageList = new List<SelectListItem>();
string defaultTitle = "Language";
foreach (var item in title)
{
languageList.Add(new SelectListItem()
{
Text = item,
Value = item,
Selected = (item == defaultTitle ? true : false)
});
}
ViewBag.LanguageList = languageList;
return View();
}
My View is as follows:
#using (Html.BeginForm("GetStatusTrad", "StatusTradController", FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Translation</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.Label("Language")
#Html.DropDownList("lang", new SelectList(ViewBag.LanguageList, "Text", "Value"), "Language")
</div>
</div>
<div></div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
}
It displays the dropdown correctly, but when I want to pass the selected value to an action of the controller, I get a 404 error.
My action is :
public ActionResult GetStatusTrad(string language)
{
*some code*
}
Any idea why I can't pass the selected value of the dropdown to the controller?
Your helper should be:
#Html.DropDownList("language", <-- note this
new SelectList(ViewBag.LanguageList, "Text", "Value"), "Language")
It happend becose basically your helper will be rendered to input like this:
<select name="language">
...
</select>
And on form POST your controller will be able to bind your values based on name property of input.
#Html.DropDownList("lang", new SelectList(... generates a <select> with name="lang. You need to change the parameter in the POST method to match
public ActionResult GetStatusTrad(string lang)
As a side note, LanguageList is already IEnumerable<SelectListItem> so using new SelectList() to create another identical one is pointless. I can be just
#Html.DropDownList("lang", (IEnumerable<SelectListItem>)ViewBag.LanguageList, "Language")
You also have a typo in the BeginForm() method. It needs to be
#using (Html.BeginForm("GetStatusTrad", "StatusTrad", FormMethod.Post))
i.e. "StatusTrad", not "StatusTradController" (unless you have really named your controller StatusTradControllerController)
you can use strongly type view to return selected dropdown value.
create simple class like below
public class myModel
{
public string language { get; set; }
....
....
}
Then use this class/model in View
#model yourProject.Models.myModel
<div class="form-group">
<label class="col-lg-2 control-label">Language</label>
<div class="col-lg-5">
#Html.ValidationMessageFor(m => m.language)
#Html.DropDownListFor(m => m.language, new SelectList(ViewBag.LanguageList, "Text", "Value"), "-- Select --", new { #class = "form-control" })
</div>
</div>
Controller method look like below
[HttpPost]
public ActionResult GetStatusTrad(myModel model)
{
*some code*
}

I'm losing data on the way Controller-View-Controller. How right get Model from View?

I have the Model which contains the few properties. There are List<Point> and ThranslatingCam. The ThranslatingCam contains property which should be entered by the user.
public class TranslatingCamModel
{
public TranslatingCam Cam { get; set; }
public List<Point> Points { get; set; }
}
Now I use the Points just for visualization but in future this list will be changed by user.
In the Controller I initialize the Points list, add it to my TranslatingCamModel and send it to the View.
public ActionResult Cam()
{
TranslatingCamModel model = new TranslatingCamModel();
List<Points> points = new List<Points>();
//here I add same data to the points list
model.Points = points;
model.Cam = new TranslatingCam();
return View("TranslatingCam", model);
}
This code works as I want. My problem is further.
#model CamShaft.WebUI.Models.TranslatingCamModel
#{
ViewBag.Title = "Cam";
}
<div class="prop">
#using (Html.BeginForm("DrawTranslatingCam", "Home"))
{
#Html.LabelFor(model => model.Cam.Rmin, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.Cam.Rmin, new { htmlAttributes = new { #class = "form-control" } })
//And the same for the other Cam's properties
<input type="submit" value="Draw" />
}
</div>
//Here is my code for visualization and etc... And here I can work with the model.Points.
It works okay too, I get value for Cam but I lose my Points list.
public ActionResult DrawTranslatingCam(TranslatingCamModel model)
{
//Here I have model returned from the View
}
Here is model.Cam with entered by user data but model.Points list is null. But I initialized it before I sent it to the View..
I tried to solve using #Html.HiddenFor:
#using (Html.BeginForm("DrawTranslatingCam", "Home"))
{
#Html.LabelFor(model => model.Cam.Rmin, htmlAttributes: new { #class = "control-label col-md-2" })
#Html.EditorFor(model => model.Cam.Rmin, new { htmlAttributes = new { #class = "form-control" } })
//And the same for the other Cam's properties
#Html.HiddenFor(model => model.Points)
<input type="submit" value="Draw" />
}
In this case is returned Points list but without date (not null, just with count = 0)
So, how right I can get my Model from the View?
The code has been slightly modified for compactness and clarity.

Partial views and html forms Asp Mvc

I am attempting to render a partial view that contains a simple html form. I want to render the form from a controller as I handle the postback from an overloaded controller method. I have tried #Html.Action("ContactForm")but I get an Exception because child actions cannot redirect.
My Controller:
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult ContactForm()
{
return PartialView(new ContactForm());
}
[HttpPost]
public ActionResult ContactForm(ContactForm Contact)
{
return RedirectToAction("FormResults", new { ContactForm = Contact });
}
public ActionResult FormResults(ContactForm Contact)
{
return PartialView(Contact);
}
My Form:
#using(Html.BeginForm())
{
<h2>Contact Form</h2>
<div class="input-group">
<h4>#Html.LabelFor(m => m.FirstName, "First Name")</h4>
#Html.TextBoxFor(m => m.FirstName, new { #class = "form-control", #placeholder = "First Name" })
</div>
<div class="input-group">
<h4>#Html.LabelFor(m => m.LastName, "Last Name")</h4>
#Html.TextBoxFor(m => m.LastName, new { #class = "form-control", #placeholder = "Last Name" })
</div>
<div class="input-group">
<h4>#Html.LabelFor(m => m.Email, "Email")</h4>
#Html.TextBoxFor(m => m.Email, new { #class = "form-control", #placeholder = "Email", #type = "text" })
</div>
<input type="submit" class="btn btn-info" value="Submit" />
}
Any Help on how I would accomplish this would be appreciated.
try surrounding the form with a div and a certain id and use:
#using(Ajax.BeginForm("ContactForm","YourController",new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "yourCertainId",
HTTPMethod = "POST"
})
and your ActionMethod:
[HttpPost]
public ActionResult ContactForm(ContactForm Contact)
{
return Partial("YourPartialName", Contact });
}
make sure that you include the bundle jqueryval on the bottom of your view.
you wont need the second controller method "FormResults"
Does something like this not work for you?
I don't think you need a redirect.
[HttpPost]
public ActionResult ContactForm(ContactForm Contact)
{
return PartialView("FormResults", Contact);
}
This uses the
PartialView(string viewName, object model)
overload of the PartialView method in the Controller class.
This allows you to use a View that doesn't match the ActionResult's method name.
The same thing works for the plain "View" method as well.

mvc5 form validation update failed

I have been working on a projectbased on mvc5.
I applied a form validation on my Model class. The "compare" condition is applied User_password and User_Password_Confirm. It works perfectly on insertion. But when I have to update the information of same client bt not password, in this case my MoldeStat.Valid is "false" because I think it is because of "compare" condition on password.
Can someone tell me how Can i solve this issue?
I am facing a problem with "update".
Thank you for your help in advance
my Model class
[Required(ErrorMessage = "*")]
public string User_Password { get; set; }
[Compare("User_Password")]
[Required(ErrorMessage = "*")]
public string User_Password_Confirm { get; set; }enter code here
My controller class
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit2([Bind(Include = "User_Id,User_Nom,User_Prenom,User_Email,User_Telephone,User_Role,User_Password,User_Password_Confirm,UserCreationDate,User_Status")] User user)
{
if (ModelState.IsValid)
{
//db.Entry(user).State = EntityState.Modified;
//db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.User_Status = new SelectList(db.Account_Status, "Account_Status_ID", "Account_Status_Nom", user.User_Status);
ViewBag.User_Role = new SelectList(db.Role, "Role_Id", "Role_Name", user.User_Role);
return View("edit");
}
View of insert (just password section). Here I tried to set value of User_Password_confirm = User_password but it failed :(
<div class="form-group">
#Html.LabelFor(model => model.User_Password, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.User_Password)
#Html.ValidationMessageFor(model => model.User_Password)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.User_Password_Confirm, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.User_Password_Confirm, new { #Value = Model.User_Password })
#Html.ValidationMessageFor(model => model.User_Password_Confirm)
</div>
</div>
First, i suggest you to create two different models : UserCreateModel and UserUpdateModel for example.
Then your code will include some security breach.
if i'm user Id 275, i can change the userId in the form (even if it's hidden), this way i'm gonna be able to change email, password, firstname, lastname of any user.
What you need to do is get the Id of the logged user and change only the data that has been changed.
if (ModelState.IsValid)
{
var userfromDb = db.Users.Find(loggedUser.EmployeeId);
userfromDb .Email = user.Email;//etc...
db.SaveChanges();
return RedirectToAction("Index");
}
You may easily see a summary of all model validation errors by inserting a
#Html.ValidationSummary
on your view.

ASP MVC EF MultiSelect HTTP POST

My Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(BlogCompModel blogmodel)
{
if (ModelState.IsValid)
{
...
}
}
My View:
#model BlogProject.Models.BlogCompModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
...
<div class="form-group">
#Html.LabelFor(model => model.BlogCompModel.posts, "Property", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.ListBoxFor(model => model.posts, new MultiSelectList(Model.posts, "post_ID", "postTitle"))
#Html.ValidationMessageFor(model => model.posts.posts)
</div>
</div>
}
Error message on post:
"The parameter conversion from type 'System.String' to type 'BlogProject.Models.Posts' failed because no type converter can convert between these types."} System.Exception {System.InvalidOperationException}
As you can see, I'm not sure how to translate the HTML Multiselect list from a collection of Post_IDs to an ICollection of posts.
Thanks!
You can add another property in your BlogCompModel Model, it'll wrap all selected post in it.
public class BlogCompModel
{
//
public string[] selectedPosts { get; set; }
}
Then in your view:
#Html.ListBoxFor(model => model.selectedPosts ,
new MultiSelectList(Model.posts, "post_ID", "postTitle"))
#Html.ValidationMessageFor(model => model.selectedPosts )
In my blog MVC app, I've a multiselect for Tags and here how I add those to Post in Create action.
Index.cshtml
#model MyBlog.Core.Post
#Html.ListBox("PostTags", (MultiSelectList)ViewBag.MultiSelectList, new { #class = "form-control" })
controller
public ActionResult CreatePost([Bind(Include = "Id,Title,ShortDescription,Description,Published,PostedOn,ModifiedOn,CategoryId")] Post post, int[] postTags)
{
if (postTags != null)
{
foreach (var t in postTags)
{
var tag = _dbTag.GetById(t);
post.Tags.Add(tag);
}
}
// save to database and other stuff
return View(post);
}

Categories