Editing IEnumerable Model Property in MVC View - asp.net-mvc-2

I have a situation where I need to edit an enumerable property in a view model:
public class ViewModel
{
public MyObj Obj { get; set; }
public IEnumerable<MyObj> MyObjs = new List<MyObj>();
}
I have followed this post; controller action:
public ActionResult Index()
{
var viewModel = new ViewModel();
viewModel.Obj = new Obj() { Name = "0", Value = true };
var o1 = new MyObj() { Name = "1", Value = false };
var o2 = new MyObj() { Name = "2", Value = false };
viewModel.Objs = new List<Obj>() { o1, o2 };
return View(viewModel);
}
[HttpPost]
public ActionResult Index(ViewModel viewModel)
{
return View(viewModel);
}
The Index view as follows:
<% using (Html.BeginForm()) { %>
<table>
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<%= Html.EditorFor(x => x.Objs) %>
</table>
<br />
<input type="submit" value="Submit" />
<% } %>
And the editor template in "~/Views/Home/EditorTemplates/Obj.ascx":
<tr>
<td><%: Html.TextBoxFor(x => x.Name) %></td>
<td><%: Html.CheckBoxFor(x => x.Value) %></td>
</tr>
The issue is: browse to Index, the data shows up. The POST, and the enumerable data disappears. Stepping through, the singular "Obj" in the view model remains, so it is just the enumerable data that is disappearing.
I have been staring at this for some time now, if any one could help out it would be brilliant.
Cheers,
Tim.

Take a look at this post by Phil Haack, MVC2 doesn't natively support binding a list back to the viewmodel unless you do a little manipulation.
Update: I've looked into this a little more and think you should try adding TryUpdateModel(viewModel.MyObjs, "MyObjs"); to your Controller. This informs the modelbinder that it should use the "MyObjs" binding prefix to attach the data from the form to the collection in your ViewModel.

Related

How can I send a single string value through View Form in my webAPI?

How can I send a single string value through view from in the WebAPI made in ASP.NET core.
Here is my API:
[HttpPost]
[Route("studentlogin/{value}")]
public IActionResult StudentLogin(string value)
{
string name = String.Concat(value.Where(s => !Char.IsWhiteSpace(s)));
name = name.ToLower();
var newStudent = new Student();
newStudent.FullName = name;
db.Entry(newStudent).State = EntityState.Added;
db.SaveChanges();
var selectStudent = db.Students.Where(ss => ss.FullName == name).FirstOrDefault();
var id = selectStudent.Id;
string idToString = id.ToString();
string answer = sha384converter(idToString);
selectStudent.HashId = answer;
db.Entry(selectStudent).State = EntityState.Modified;
db.SaveChanges();
return Ok();
}
I want to send paramenter value in it through View Forms, How can I send data in it?
Thanks in advance.
[Route("studentlogin/{value}")]
If you are using the above route, the request URL should like this: https://localhost:44310/api/apicontrollername/studentlogin/XXX, the parameter will be transferred from the URL and route.
to send paramenter value in it through View Forms, How can I send data
in it?
To send parameter value from posted form fields, you could modify the code as below:
In the API controller, remote the route parameter and add the FromForm attribute.
[HttpPost]
[Route("studentlogin")]
public IActionResult StudentLogin([FromForm]string value)
{
string name = "Default value";
if (!string.IsNullOrEmpty(value))
{
name = String.Concat(value.Where(s => !Char.IsWhiteSpace(s)));
}
... // add your code
return Ok(name);
}
Then, create a model which contain the value property, like this:
public class StudentLoginViewModel
{
public string value { get; set; }
}
In the View page, display the above model in the form:
#model WebApplication6.Models.StudentLoginViewModel;
<form id="myform">
<div class="form-group">
<label asp-for="value" class="control-label"></label>
<input asp-for="value" class="form-control" />
<span asp-validation-for="value" class="text-danger"></span>
</div>
<div class="form-group">
<input type="button" id="btnsubmit" value="Submit" class="btn btn-primary" />
</div>
</form>
and add the following script at the end of the above view page:
#section Scripts{
<script>
$(function () {
$("#btnsubmit").click(function () {
//use the serialize() method to encode a set of form elements as a string for submission
var data = $("#myform").serialize();
//you can also create JavaScript object and send the data.
//var data = { value: $("#value").val() };
$.ajax({
url: '/api/todo/studentlogin', // change the url to yours.
type: "post",
contentType: 'application/x-www-form-urlencoded',
data: data,
success: function (result) {
console.log(result);
}
});
});
})
</script>
}
The result as below:

MVC 5 - How to pull emdx data from controller to view

New to MVC! I can pull data from my Database first Entity Framework model (emdx) just fine... Works Great - Coolest thing ever! But I have 2 questions:
1) I cannot get the data back to my view. (I want to display the security question (being returned from my stored proc in my DB First Entity Data Model - emdx) and allow the user to answer the question.
2) I also can't seem to redirect to a view in a different view folder (from the "View\Account" folder to the "View\Home" folder.
I'm pretty sure this is easy and I'm just missing something basic.
Here is my MVC controller code:
public ActionResult Login(LoginViewModel model, string returnUrl)
{
string strEncr = "";
try
{
if (ModelState.IsValid)
{
//Create Hash with Salt for For New PWs
strEncr = Helper.ComputeHash(model.Password, "SHA512", null);
string DBPW = "";
string encryptedPassword = "";
try
{
using (var context = new WMSEntities1())
{
encryptedPassword = context.users
.Where(u => u.emailAddress == model.Username)
.Select(u => u.password)
.SingleOrDefault();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//Test for match of PW between User and what's stored in DB
bool flag = Helper.VerifyHash(model.Password, "SHA512", encryptedPassword);
var loginInfo = databaseManager.LoginAndGetSecQuestion(model.Username, encryptedPassword).ToList();
// Verification.
if (loginInfo != null && loginInfo.Count() > 0)
{
// Initialization.
var logindetails = loginInfo.First();
// Login In.
this.SignInUser(logindetails.emailAddress, false);
ViewBag.SecurityQuestion = logindetails.securityQuestion;
// Info.
return View("~/Views/Home/Index.cshtml", loginInfo);
// return this.RedirectToLocal(returnUrl);
}
else
{
// Setting.
ModelState.AddModelError(string.Empty, "Invalid username or password.");
}
}
}
catch (Exception ex)
{
// Info
Console.Write(ex);
}
// If we got this far, something failed, redisplay form
return this.View(model);
}
Here is my code snipets in my view:
#*#model System.Data.DataSet*#
#model AodNetIntegration.LoginAndGetSecQuestion_Result
#{
ViewBag.Title = "Doc Center Login Screen";
}
#*<h2>#ViewBag.Title.</h2>http://asmak9.blogspot.com/2016/03/aspnet-mvc5-integrating-existing.html
<h3>#ViewBag.Message</h3>*#
#using (Html.BeginForm("LoginStage2", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<table cellspacing="5" style="width: 293px;">
<tr>
<td></td>
</tr>
<tr>
<td>
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.LabelFor(m => m.securityQuestion, new { #class = "col-md-2 control-label, width= 50" })
#Html.DisplayFor(m => m.securityQuestion, new { #class = "col-md-2 control-label, width= 50" })
#Html.ValidationMessageFor(m => m.securityQuestion, "", new { #class = "text-danger" })<br />
#Html.LabelFor(m => m.securityQuestionAnswer, new { #class = "col-md-2 control-label" })
#Html.PasswordFor(m => m.securityQuestionAnswer, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.securityQuestionAnswer, "", new { #class = "text-danger" })
</td>
</tr>
<tr>
<td align="right" style="text-align: right;">
<input type="submit" value="Submit" class="btn btn-default" />
</td>
</tr>
</table>
Here is the error I get:
When it goes back to the Index page:
The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[AodNetIntegration.LoginAndGetSecQuestion_Result]', but this dictionary requires a model item of type 'AodNetIntegration.LoginAndGetSecQuestion_Result'.
Controller Model Method:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace AodNetIntegration
{
using System;
public partial class LoginAndGetSecQuestion_Result
{
public int userID { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string securityQuestion { get; set; }
public string emailAddress { get; set; }
public string securityQuestionAnswer { get; set; }
}
}
Thanks,
Your query (var loginInfo = databaseManager....) is returning a collection of LoginAndGetSecQuestion_Result, not a single object, and you then return that collection to the view using
return View("~/Views/Home/Index.cshtml", loginInfo);
but you view expects a single LoginAndGetSecQuestion_Result object, not a collection.
You code should be
return View("~/Views/Home/Index.cshtml", logindetails);
However you can simplify your code by modifying the query to return a single object and testing for null
var loginInfo = databaseManager.LoginAndGetSecQuestion(model.Username, encryptedPassword).FirstOrDefault();
if (loginInfo != null)
{
this.SignInUser(loginInfo.emailAddress, false);
ViewBag.SecurityQuestion = logindetails.securityQuestion;
return View("~/Views/Home/Index.cshtml", loginInfo);
}
else
{
ModelState.AddModelError(string.Empty, "Invalid username or password.");
}

Passing parameters to MVC Ajax.ActionLink

How can I send the value of the TextBox as a parameter of the ActionLink?
I need to use the Html.TextBoxFor
<%= Html.TextBoxFor(m => m.SomeField)%>
<%= Ajax.ActionLink("Link Text", "MyAction", "MyController", new { foo = "I need here the content of the textBox, I mean the 'SomeField' value"}, new AjaxOptions{ UpdateTargetId = "updateTargetId"} )%>
The Contoller/Actions looks like this:
public class MyController{
public ActionResult MyAction(string foo)
{
/* return your content */
}
}
Using MVC 2.0
How can I send the value of the TextBox as a parameter of the ActionLink?
The semantically correct way of sending input fields values (such as textboxes) to a server is by using an html <form> and not links:
<% using (Ajax.BeginForm("MyAction", "MyController", new AjaxOptions { UpdateTargetId = "updateTargetId" })) { %>
<%= Html.TextBoxFor(m => m.SomeField) %>
<input type="submit" value="Link Text" />
<% } %>
Now in your controller action you will automatically get the value of the SomeField input entered by the user:
public class MyController: Controller
{
public ActionResult MyAction(string someField)
{
/* return your content */
}
}
You could of course try to violate the markup semantics and the way HTML is supposed to work by insisting on using an ActionLink even if it is wrong. In this case here's what you could do:
<%= Html.TextBoxFor(m => m.SomeField) %>
<%= Html.ActionLink("Link Text", "MyAction", "MyController", null, new { id = "myLink" }) %>
and then in a separate javascript file unobtrusively AJAXify this link using jQuery:
$(function() {
$('#myLink').click(function() {
var value = $('#SomeField').val();
$('#updateTargetId').load(this.href, { someField: value });
return false;
});
});

Images being displayed as weird characters

In this project I'm trying to implement a price list (it's a taxidermy site) So here's what I'm going to do, show you the code
PriceListController
public partial class PriceListController : Controller
{
public PriceListController()
{
}
[CanonicalUrlAttribute("PriceList")]
[CompressionFilter(Order = 1)]
[CacheFilter(Duration = 120, Order = 1)]
public virtual ActionResult Index()
{
GodsCreationTaxidermyEntities context = new GodsCreationTaxidermyEntities();
var viewModel = new PriceListViewModel() { PriceListAnimals = context.GetAnimalListForPriceList() };
return View(viewModel);
}
[CompressionFilter(Order = 1)]
[CacheFilter(Duration = 120, Order = 2)]
public virtual ActionResult List(string animal)
{
GodsCreationTaxidermyEntities context = new GodsCreationTaxidermyEntities();
var viewModel = new PriceListIndexViewModel() { AnimalPrices = context.GetPriceListByAnimal(animal) };
return View(viewModel);
}
}
The index work fine. Here's Index.aspx
Index.aspx
<div id="main-content" title="AnimalBox" style="float:none;">
<%--<%= Html.DropDownList("AnimalList", Model.Animals, "[Select One]", new { #class = "inputDropDown" })%>--%>
<% Html.DataList(Model.PriceListAnimals).Columns(6).Item(item =>
{
item.Template(galleryImage =>
{%>
<div style="margin-right:45px; line-height:150%;">
<span><%= Html.ActionLink(galleryImage.AnimalName,"List",new { #animal = galleryImage.AnimalName }) %></span>
</div>
<% });
}).Render(); %>
</div>
Now we move on to the listing page
List.aspx
<div class="maintext" id="pricelist">
<h2 class="sectionHeader">:: Gods Creation Taxidermy : PriceList ::</h2>
<% Html.DataList(Model.AnimalPrices).Columns(7).Item(item =>
{
item.Template(galleryImage =>
{%>
<div><%=galleryImage.TypeName %></div>
<%});
}).Render(); %>
<% Html.DataList(Model.AnimalPrices).Columns(7).Item(item2 =>
{
item2.Template(galleryImage =>
{%>
<div><%=galleryImage.MountPrice %></div>
<% });
}).Render(); %>
</div>
Here's a screenshot of how this is beeing displayed
Screenshot
If anyone couod hekp I'd surely be grately.
EDIT: By the way the images arent being stored in a DB, just the path, which makes this even more fonfusing.
This issue is resolved, I have a couple things backwards

How to Set RadioButtonFor() in ASp.net MVC 2 as Checked by default

How can i Set RadioButtonFor() as Checked By Default
<%=Html.RadioButtonFor(m => m.Gender,"Male")%>
there is way out for (Html.RadioButton) but not for (Html.RadioButtonFor)
any Ideas?
Use the simple way:
<%= Html.RadioButtonFor(m => m.Gender, "Male", new { Checked = "checked" })%>
It's not too pretty, but if you have to implement only very few radio buttons for the entire site, something like this might also be an option:
<%=Html.RadioButtonFor(m => m.Gender,"Male",Model.Gender=="Male" ? new { #checked = "checked" } : null)%>
I assume you should have a group of radio buttons. something could be like
<%=Html.RadioButtonFor(m => m.Gender,"Male")%>
<%=Html.RadioButtonFor(m => m.Gender,"Female")%>
<%=Html.RadioButtonFor(m => m.Gender,"Unknown")%>
You may give the default value for m.Gender = "Unknown" (or something) from your controller.
This question on StackOverflow deals with RadioButtonListFor and the answer addresses your question too. You can set the selected property in the RadioButtonListViewModel.
This Helper evaluates the expression and if equals to the value it checks the radio button, and has the same parameters than RadioButtonFor (for this reason the name is diferent):
public static MvcHtmlString CheckedRadioButtonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value)
{
return CheckedRadioButtonFor(htmlHelper, expression, value, null);
}
public static MvcHtmlString CheckedRadioButtonFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object value, object htmlAttributes)
{
var func = expression.Compile();
var attributes = new RouteValueDictionary(htmlAttributes);
if ((object)func(htmlHelper.ViewData.Model) == value) {
attributes["checked"] = "checked";
}
return htmlHelper.RadioButtonFor(expression, value, attributes);
}
Usage:
<%= Html.CheckedRadioButtonFor(m => m.Gender, "Male", new { id = "gender-male" })%>
Result:
<!-- For Model.Gender = "Male" -->
<input checked="checked" id="gender-male" name="Gender" type="radio" value="Male">
<!-- For Model.Gender = "Female" -->
<input id="gender-male" name="Gender" type="radio" value="Male">
I found another option so you can just use #Html.EditorFor() with templates:
Say I have this enum:
public enum EmailType { Pdf, Html }
I can put this code in Views/Shared/EditorTemplates/EmailType.cshtml
#model EmailType
#{
var htmlOptions = Model == EmailType.Html ? new { #checked = "checked" } : null;
var pdfOptions = Model == EmailType.Pdf ? new { #checked = "checked" } : null;
}
#Html.RadioButtonFor(x => x, EmailType.Html, htmlOptions) #EmailType.Html.ToString()
#Html.RadioButtonFor(x => x, EmailType.Pdf, pdfOptions) #EmailType.Pdf.ToString()
Now I can simply use this if I want to use it at any time:
#Html.EditorFor(x => x.EmailType)
It's much more universal this way, and easier to change I feel.
Came across this and thought I would point out that for MVC 5 all you need to do is set the value on the model. For Example:
Model:
public class ExampleModel
{
public PackingListInputModel()
{
RadioButtonField = "One";
}
public string RadioButtonField { get; set; }
}
View :
#model ExampleModel
#using (Html.BeginForm)
{
#Html.RadioButtonFor(m => m.RadioButtonField , "One")
#Html.RadioButtonFor(m => m.RadioButtonField , "Two")
}
The state of the first radio button ("One") will be set as active because the value matches what was set in the model.
You can also add labels that are tied to your radio buttons with the same ID, which then allows the user to click the radio button or label to select that item. I'm using constants here for "Male", "Female" and "Unknown", but obviously these could be strings in your model.
<%: Html.RadioButtonFor(m => m.Gender, "Male",
new Dictionary<string, object> { { "checked", "checked" }, { "id", "Male" } }) %>
<%: Html.Label("Male") %>
<%: Html.RadioButtonFor(m => m.Gender, "Female",
new Dictionary<string, object> { { "id", "Female" } }) %>
<%: Html.Label("Female")%>
<%: Html.RadioButtonFor(m => m.Gender, "Unknown",
new Dictionary<string, object> { { "id", "Unknown" } }) %>
<%: Html.Label("Unknown")%>
<%: Html.RadioButtonFor(m => m.Gender, "Male", new { #checked = true } )%>
or
#checked = checked
if you like
If you're using jquery, you can call this right before your radio buttons.
$('input:radio:first').attr('checked', true);
^ This will check the first radio box, but you can look at more jquery to cycle through to the one you want selected.
#Html.RadioButton("Insured.GenderType", 1, (Model.Insured.GenderType == 1 ))
#Web.Mvc.Claims.Resources.PartyResource.MaleLabel
#Html.RadioButton("Insured.GenderType", 2, Model.Insured.GenderType == 2)
#Web.Mvc.Claims.Resources.PartyResource.FemaleLabel
Here is code to set default radio button set to true
#Html.RadioButtonFor(m => m.Gender, "Male", new { #checked = "checked", id = "rdGender", name = "rbGender" })
I find it best to just put the default value in the constructor method of the model.
Gender = "Male";
You need to add 'checked' htmlAttribute in RadioButtonFor, if the radiobutton's value matches with Model.Gender value.
#{
foreach (var item in Model.GenderList)
{
<div class="btn-group" role="group">
<label class="btn btn-default">
#Html.RadioButtonFor(m => m.Gender, item.Key, (int)Model.Gender==item.Key ? new { #checked = "checked" } : null)
#item.Value
</label>
</div>
}
}
For complete code see below link: To render bootstrap radio button group with default checked.
stackoverflow answer link