Blazor InputCheckbox binding to string backing field - checkbox

I am trying to make a dynamic form system and I want to be able to bind an InputCheckbox to a database field that's a string rather than a bool...
<EditForm Model="#theEntryResults" OnValidSubmit="#SaveEntries">
<div class="row">
<div class="col-6">
#foreach (var entry in theEntryResults)
{
<div class="form-group m-2">
<label>
#entry.Field.FieldName:
#switch (entry.Field.FieldTypeID)
{
case 0:
<InputText #bind-Value="#entry.Value" class="form-control"></InputText>
break;
case 1:
<InputSelect #bind-Value="#entry.Value" class="form-select">
<option value=""></option>
#foreach (var option in entry.Field.Choices)
{
<option value="#option.Value">#option.Name</option>
}
</InputSelect>
break;
case 2:
<InputCheckbox #bind-Value="#MyValue" class="form-check-inline" style="width: 50px; height: 50px;"></InputCheckbox>
break;
}
</label>
</div>
}
</div>
</div>
<button class="btn btn-success" type="submit">Save</button>
</EditForm>
is what I am trying but entry.Value is a string and so this is giving me "Cannot convert string to bool"
Any ideas?
Thanks!

Bind it to a bool in your code section of the component and then translate in the getters and setters of that.
<InputCheckbox #bind-Value=#MyValue />
#code {
bool MyValue
{
get => Convert.ToBoolean(entry.Value);
set => entry.Value = value.ToString();
}
}
As you are using a for each loop, my recommendation would be to use a child-component for each entry (e.g. EntryViewComponent), so that each child-component is focused on working with an individual entry. In this way, the above suggestion would still apply.
#foreach (var entry in theEntryResults)
{
<EntryViewComponent Entry=#entry />
}
EntryViewComponent
<markup that was previously in the for-each loop>
#code {
[Parameter] public EntryClass Entry { get; set; }
// similar code to first suggestion above
}
If you wish to continue using mark-up inside the for each loop instead of a component, the following may work:
<InputCheckbox Value=#(Convert.ToBoolean(entry.Value))
ValueChanged=#((v) => entry.Value = v.ToString()) />
In this code, instead of auto-binding, you are using different code for the setting of the value of the checkbox and the handling of a value change from the checkbox.

An example to bind string to an InputCheckbox would be by using a component where the string can be converted to boolean and bind to InputCheckBox and vice versa.
Component:
#* MyInputCheckBox.razor *#
<InputCheckbox #bind-Value="isCheck"
class="form-check-inline"
style="width: 50px; height: 50px;"/>
#code {
[Parameter]
public string CheckValueStr { get; set; }
[Parameter]
public EventCallback<string> CheckValueStrChanged { get; set; }
private bool _isCheck;
public bool isCheck
{
get { return _isCheck; }
set {
_isCheck = value;
CheckValueStrChanged.InvokeAsync(value.ToString());}
}
protected override void OnInitialized()
{
isCheck = bool.Parse(CheckValueStr);
}
}
Page:
#page "/"
#using BlazorApp2.Components
<EditForm Model="sample">
<MyInputCheckBox #bind-CheckValueStr="#sample.CheckValue" />
</EditForm>
<br/>
#sample.CheckValue
#code {
private Sample sample = new Sample();
public class Sample
{
public string CheckValue = "false";
}
}
Output:

Related

Save ASP.NET core Identity User attributes in another table

I am developing an ASP .NET core web application. I employ Identity UI framework for the user registration and authorization in the application. I inherit Identity User to my ApplicationUser class as follows. It creates a table called as ApplicationUser and save the relevant data under the given attributes successfully: (I am using Microsoft SQL database)
ApplicationUser.cs
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
#nullable disable
namespace WebApp.Models
{
public partial class ApplicationUser : IdentityUser<int>
{
public ApplicationUser()
{
}
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastNam { get; set; }
public DateTime? DateOfBirth { get; set; }
public string Bio { get; set; }
public virtual UserAddress UserAddress { get; set; }
}
}
Then I implemented UserAddress model class as follows. It creates another table in the database named as "UserAddress"\
UserAddress.cs
using System;
using System.Collections.Generic;
#nullable disable
namespace WebApp.Models
{
public partial class UserAddress
{
public int UserId { get; set; }
public string BuildingNo { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public virtual ApplicationUser User { get; set; }
}
}
Next in under Areas folder in Identity UI frame work, I change the Index.cshtml file as follows. i inserting new entry to enter the building number of the user, that should be saved in UserAddress table in database.
Index.cshtml
#page
#model IndexModel
#{
ViewData["Title"] = "Profile";
ViewData["ActivePage"] = ManageNavPages.Index;
}
<h4>#ViewData["Title"]</h4>
<partial name="_StatusMessage" model="Model.StatusMessage" />
<div class="row">
<div class="col-md-12">
<form id="profile-form" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="=row d-flex flex-row">
<div class="form-group col-md-6">
<label asp-for="Input.UserName"></label>
<input asp-for="Input.UserName" class="form-control" />
</div>
</div>
<div class="=row d-flex flex-row">
<div class="form-group col-md-6">
<label asp-for="Input.FirstName"></label>
<input asp-for="Input.FirstName" class="form-control" />
</div>
<div class="form-group col-md-6">
<label asp-for="Input.MiddleName"></label>
<input asp-for="Input.MiddleName" class="form-control" />
</div>
</div>
<div class="=row d-flex flex-row">
<div class="form-group col-md-6">
<label asp-for="Input.LastNam"></label>
<input asp-for="Input.LastNam" class="form-control" />
</div>
</div>
<div class="=row d-flex flex-row">
<div class="form-group col-md-6">
<label asp-for="Input.DateOfBirth"></label>
<input asp-for="Input.DateOfBirth" class="form-control" />
</div>
<div class="form-group col-md-6">
<label asp-for="Input.PhoneNumber"></label>
<input asp-for="Input.PhoneNumber" class="form-control" />
<span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
</div>
</div>
<div class="=row d-flex flex-row">
<div class="form-group col-md-6">
<label asp-for="Input.BuildingNo"></label>
<input asp-for="Input.BuildingNo" class="form-control" />
</div>
</div>
<div class="=row d-flex flex-row">
<div class="do-md-6">
<button id="update-profile-button" type="submit" class="btn btn-primary">Save</button>
</div>
</div>
</form>
</div>
</div>
#section Scripts {
<partial name="_ValidationScriptsPartial" />
}
And in the Index.cshtml.cs file, I tried to save the building number in the UserAddress table as follows but it fails to enter the data into the table.
Index.cshtml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using WebApp.Models;
namespace WebApp.Areas.Identity.Pages.Account.Manage
{
public partial class IndexModel : PageModel
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
public IndexModel(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
public string BuildingNo { get; set; }
public string Username { get; set; }
[TempData]
public string StatusMessage { get; set; }
[BindProperty]
public InputModel Input { get; set; }
public class InputModel
{
[DataType(DataType.Text)]
[Display(Name = "User Name")]
public string UserName { get; set; }
[DataType(DataType.Text)]
[Display(Name = "First name")]
public string FirstName { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Middle name")]
public string MiddleName { get; set; }
[DataType(DataType.Text)]
[Display(Name = "Last name")]
public string LastNam { get; set; }
[Display(Name = "Date of Birth")]
[DataType(DataType.Date)]
public DateTime DateOfBirth { get; set; }
[Phone]
[Display(Name = "Phone number")]
public string PhoneNumber { get; set; }
[Display(Name = "Building No:")]
[DataType(DataType.Text)]
public string BuildingNo { get; set; }
}
private async Task LoadAsync(ApplicationUser user)
{
var userName = await _userManager.GetUserNameAsync(user);
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
Username = userName;
Input = new InputModel
{
UserName = user.UserName,
FirstName = user.FirstName,
MiddleName = user.MiddleName,
LastNam = user.LastNam,
PhoneNumber = phoneNumber,
};
}
public async Task<IActionResult> OnGetAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
await LoadAsync(user);
return Page();
}
public async Task<IActionResult> OnPostAsync()
{
var user = await _userManager.GetUserAsync(User);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
if (!ModelState.IsValid)
{
await LoadAsync(user);
return Page();
}
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
if (Input.PhoneNumber != phoneNumber)
{
var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
if (!setPhoneResult.Succeeded)
{
StatusMessage = "Unexpected error when trying to set phone number.";
return RedirectToPage();
}
}
if(Input.FirstName != user.FirstName)
{
user.FirstName = Input.FirstName;
}
if (Input.MiddleName != user.MiddleName)
{
user.MiddleName = Input.MiddleName;
}
if (Input.LastNam != user.LastNam)
{
user.LastNam = Input.LastNam;
}
if (Input.DateOfBirth != user.DateOfBirth)
{
user.DateOfBirth = Input.DateOfBirth;
}
if (Input.UserName != user.UserName)
{
user.UserName = Input.UserName;
}
user.UserAddress.BuildingNo = Input.BuildingNo; // I tried to enter the building address to the UserAddress table by using this code
await _userManager.UpdateAsync(user);
await _signInManager.RefreshSignInAsync(user);
StatusMessage = "Your profile has been updated";
return RedirectToPage();
}
}
}
Please ignore the above lengthy Index.cshtml.cs code I have provided, I have commented near the only code that I used to insert the input building number to the UserAddress table. which is:
user.UserAddress.BuildingNo = Input.BuildingNo;
This is the part of view of the entry: The entry view
And this is the error I am getting when above code is run: The error message
For the record: all the fields in ApplicationUser table is updated. but this error occurs when I am trying to insert data into UserAddress table.
I am pretty user this is a very simple question for a person who knows ASP.NET core identity user very well.
I kindly request if somebody can please help me to save the input building number in another table named User Address?
Thanks in advance !!!
You can change your code like below:
First use code get current user include UserAddress:
var user = await _userManager.Users
.Include(x => x.UserAddress)
.SingleAsync(x => x.UserName== Input.UserName);
Then determine whether UserAddress exists and update it.
if (user.UserAddress == null)
{
user.UserAddress = new Models.UserAddress
{
BuildingNo = Input.BuildingNo
};
}
else
{
user.UserAddress.BuildingNo = Input.BuildingNo;
}
The whole code is like below:
public async Task<IActionResult> OnPostAsync()
{
//get the current user
var user = await _userManager.Users
.Include(x => x.UserAddress)
.SingleAsync(x => x.UserName== Input.UserName);
if (user == null)
{
return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
if (!ModelState.IsValid)
{
await LoadAsync(user);
return Page();
}
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
if (Input.PhoneNumber != phoneNumber)
{
var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
if (!setPhoneResult.Succeeded)
{
StatusMessage = "Unexpected error when trying to set phone number.";
return RedirectToPage();
}
}
if(Input.FirstName != user.FirstName)
{
user.FirstName = Input.FirstName;
}
if (Input.MiddleName != user.MiddleName)
{
user.MiddleName = Input.MiddleName;
}
if (Input.LastNam != user.LastNam)
{
user.LastNam = Input.LastNam;
}
if (Input.DateOfBirth != user.DateOfBirth)
{
user.DateOfBirth = Input.DateOfBirth;
}
if (Input.UserName != user.UserName)
{
user.UserName = Input.UserName;
}
//insert the BuildingNo
if (user.UserAddress == null)
{
user.UserAddress = new Models.UserAddress
{
BuildingNo = Input.BuildingNo
};
}
else
{
user.UserAddress.BuildingNo = Input.BuildingNo;
}
await _userManager.UpdateAsync(user);
await _signInManager.RefreshSignInAsync(user);
StatusMessage = "Your profile has been updated";
return RedirectToPage();
}

Can't post (create) 3rd level nested model in ASP.NET Core 3.1 MVC

I'm at the end of my thoughts. It's been days. I can't figure out how to validate and then create a new database model from deep-nested models.
I have Offer and Order tables which share Company/Currency/Contact tables so I decided, instead of having Offer.Company, Order.Company, to create a table SharedInfo and have it Offer.SharedInfo.Company and Order.SharedInfo.Comapany which can be the same.
Shortened for brevity
Company.cs:
namespace memo.Models
{
public partial class Company
{
[Key]
public int CompanyId { get; set; }
[Required(ErrorMessage = "You have to fill the name of the Company")]
public string Name { get; set; }
public string City { get; set; }
}
}
SharedInfo.cs:
namespace memo.Models
{
public class SharedInfo
{
public SharedInfo()
{
Company = new Company();
}
[Key]
public int SharedInfoId { get; set; }
[Required]
public string Subject { get; set; }
[Required]
public int CompanyId { get; set; }
public virtual Company Company { get; set; }
Offer.cs:
namespace memo.Models
{
public partial class Offer
{
public Offer()
{
SharedInfo = new SharedInfo();
}
[Key]
public int OfferId { get; set; }
public int SharedInfoId { get; set; }
public virtual SharedInfo SharedInfo { get; set; }
}
}
My view model for Create.cshtml file is (again, for brevity shortened but this fills my combobox and references the Offer):
namespace memo.ViewModels
{
public class OfferViewModel
{
public Offer Offer { get; set; }
public IEnumerable<SelectListItem> CompanyList { get; set; }
}
}
Now I want to create a new offer where I select CompanyId from a combobox.
Offers/Create.cshtml:
#model memo.ViewModels.OfferViewModel
<div class="container d-flex justify-content-center">
<div class="col-lg-10 personal-info">
<form class="card" role="form" autocomplete="on" asp-action="Create" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group row">
<label asp-for="Offer.SharedInfo.Subject" class="required col-lg-3 col-form-label form-control-label control-label"></label>
<div class="col-lg-9">
<span class="has-float-label">
<input asp-for="Offer.SharedInfo.Subject" class="form-control" type="text" />
<label asp-for="Offer.SharedInfo.Subject"></label>
</span>
<span asp-validation-for="Offer.SharedInfo.Subject" class="text-danger"></span>
</div>
</div>
<div class="form-group row">
<label class="required col-lg-3 col-form-label form-control-label control-label"></label>
<div class="col-lg-4">
<select class="form-control selectpicker" asp-for="Offer.SharedInfo.Company.CompanyId" asp-items="#Model.CompanyList"></select>
<span asp-validation-for="Offer.SharedInfo.Company.CompanyId" class="text-danger"></span>
</div>
</div>
Here I select a company which gives me the CompanyId, no problem there.
But now, when I click on Create Offer button to Post the form, the validation fails...
Offers/OffersController.cs
[HttpPost]
public async Task<IActionResult> Create(Offer offer)
{
if (ModelState.IsValid)
{
offer.CreatedBy = User.GetLoggedInUserName();
offer.CreatedDate = DateTime.Now;
await _db.AddAsync(offer);
await _db.SaveChangesAsync();
}
}
Validation tells me that:
SubKey={Name}, Key="offer.SharedInfo.CompanyName", ValidationState=Invalid
What I want to achieve is to Create 2 new tables. SharedInfo which will reference the Company by ID I selected and then Offer, which will reference the new SharedInfo record.
Am I doing something horribly wrong? It's telling me I have to "it's required" specify Company.Name but when I select the company by it's ID, it should know the name...
I even tried in the controller to specify _context.Offer.SharedInfo.Company = _context.Company.Where(x => x.CompanyId == offer.SharedInfo.Company.CompanyId) but that fails in >> Validation << because, I think, the SharedInfo is not yet created? Don't know. I'm totally at the end with my thoughts.
Model validation will validate the whole model if you specify any of their property in your razor view.For you contains input named Offer.SharedInfo.Company.CompanyId and Offer.SharedInfo.Subject,model validation will validate all the properties in Company model and 'SharedInfo' model although you do not set CompanyName input.
And I think you may be confused that Offer.SharedInfo.CompanyId which is required but you also do not set input in razor view.Because it is an int type,you could see that it will receive default value 0 if you do not pass the value to backend.And 0 is a valid value for int type,that is why the validation for Offer.SharedInfo.CompanyId succeed.
For your requirement,you want to skip the validation of CompanyName,you could use ModelState.Remove(keyname) like below:
[HttpPost]
public async Task<IActionResult> Create(Offer offer)
{
ModelState.Remove("Offer.SharedInfo.CompanyName");//from your error message,it should be the key name
if (ModelState.IsValid)
{
//...
}
//...
}

My controller get null value when i get list by id

why my controller gets the null value for Address, Phone, UserName, Email?
When i debug, Payment2 POST has received id from view and has a value.
My controller:
[HttpGet]
public ActionResult Payment2(int id)
{
model md = new model();
var pm = new paymentmodel();
var cart = Session[CartSession];
if (cart != null)
{
md.v1 = (List<CartItemModel>)cart;
}
md.v2 = pm.userdetails(id);
return View(md);
}
[HttpPost]
public ActionResult Payment2(int id, User c)
{
var cart = (List<CartItemModel>)Session[CartSession];
foreach (var item in cart)
{
if (item.quantity > item.Product.suspended)
{
return Redirect("/loi-so-luong");
}
}
var oder = new HoaDon();
oder.Date = DateTime.Now;
oder.Address = c.Address;
oder.Phone = c.Phone;
oder.TenNguoiNhan = c.UserName;
oder.E_mail = c.Email;
}
return Redirect("/hoan-thanh");
}
NULL with Address, Phone, UserName, Email
My model.cs:
public class model
{
public List<CartItemModel> v1 { set; get; }
public List<get_customer_Result> v2 { set; get; }
}
My paymentmodel:
public class paymentmodel
{
KINHDOANHVLXDEntities ke = new KINHDOANHVLXDEntities();
public List<get_customer_Result> userdetails(int id)
{
var ln = ke.get_customer(id);
return ln.ToList();
}
}
My index view:
#model List<thuctaplan2.Models.CartItemModel>
#using thuctaplan2.Common
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
var session = (UserLogin)Session[CommonConstants.USER_SESSION];
}
Thanh Toán
My Payment2 View:
#model thuctaplan2.Models.model
#{
ViewBag.Title = "Thanh Toán";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm("Payment2", "Cart", FormMethod.Post))
{
foreach (var item in Model.v2)
{
<div class="form-group">
<label>Name</label>
<label>#item.UserName</label>
</div>
<div class="form-group">
<label>Phone</label>
<label>#item.Phone</label>
</div>
<div class="form-group">
<label>Address</label>
<label>#item.Address</label>
</div>
<div class="form-group">
<label>E-mail</label>
<label>#item.Email</label>
</div>
}
<button type="submit" class="btn">Send</button>
}
What is happening here based on your code is that when you render your view, all your controls inside your Form is empty or with no value, in short, null. Why? Because you only render label html elements inside your Form.
In order to have a value, add a textbox like this:
#Html.TextBoxFor(modelItem => item.UserName, new { #class = "form-control" })
So that when you submit your Form, your User model properties like UserName will have a value. If this are all labels only, no value will be passed to your controller.

How to Upload 2 Image Files into MVC C# 5 database in its respective Byte[] array property?

public class Opportunity
{
[Key]
public int OpportunityId { get; set; }
[Required(ErrorMessage = "Graphics Image is required")]
public byte[] Graphics { get; set; }
[DisplayName("Faculty Picture")]
[Required(ErrorMessage = "Faculty Image is required")]
public byte[] FacultyPicture { get; set; }
}
Controller:
namespace Kaust.Views.Opportunities
{
public class OpportunitiesController : Controller
{
private KaustContext db = new KaustContext();
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "OpportunityId,Graphics,FacultyPicturen")] Opportunity opportunity)
{
if (ModelState.IsValid)
{
db.Opportunities.Add(opportunity);
db.SaveChanges();
return RedirectToAction("Index");
}
}
View:
Create index:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Opportunity</h4>
<hr />
#Html.Images(m => m.Graphics, "Graphics", "id")
#Html.ValidationMessageFor(model => model.Graphics, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-horizontal">
<h4>Opportunity</h4>
<hr />
#Html.Images(m => m.FacultyPicture, "Graphics", "id")
#Html.ValidationMessageFor(model => model.FacultyPicture, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
And #Html.Images is a customhelper:
public static IHtmlString Images<TModel,TValue>(this HtmlHelper<TModel> helper,System.Linq.Expressions.Expression<Func<TModel, TValue>> expression, string name, string id){
TagBuilder tb = new TagBuilder("input");
tb.Attributes.Add("ex", expression.ToString());
tb.Attributes.Add("name", name);
tb.Attributes.Add("id", id);
tb.Attributes.Add("type", "file");
tb.Attributes.Add("accept", "Image/*");
return new MvcHtmlString(tb.ToString(TagRenderMode.SelfClosing));
}
}
It creates this output:
<input accept="Image/*" ex="m => m.Graphics" id="id" name="Graphics" type="file">
When I click the submit button:
The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
I have seend several methods to change the image file to Byte[] but I just don't know how to do it before the submit button or because it doesn't get into the "httppost method".
I have tried this solutions. but... I still get the error.
How to upload/display images using ASP.net MVC4 with Entity Framework
http://www.prideparrot.com/blog/archive/2012/8/uploading_and_returning_files
The question is how can I save this files into the databases in after clicking the submit button?
The properties in your model need to be HttpPostedFileBase (not byte[]) for binding to a file input in the view. Since your also wanting to store the filein the data base, you will need a separate view model and data model
// View model (Note ID property not required)
public class OpportunityVM
{
[Required(ErrorMessage = "Image is required")]
public HttpPostedFileBase Graphics { get; set; }
[DisplayName("Faculty Picture")]
public HttpPostedFileBase FacultyPicture { get; set; }
}
And in the POST method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([OpportunityVM model)
{
if(!ModelState.IsValid)
{
return View(model);
}
// Initialize data model
Opportunity opportunity = new Opportunity();
using (var reader = new System.IO.BinaryReader(model.Graphics.InputStream))
{
opportunity.Graphics = reader.ReadBytes(model.Graphics.ContentLength);
}
if (model.FacultyPicture != null && modelFacultyPicture.ContentLength > 0)
{
// ditto for FacultyPicture
}
db.Opportunities.Add(opportunity);
db.SaveChanges();
return RedirectToAction("Index");
}
Note that you also need to include the enctype = "multipart/form-data" attribute in the form tag
#using (Html.BeginForm("Create", "Opportunities", FormMethod.Post, new { enctype = "multipart/form-data" }))
Side note: Your generating invalid html. Both file inputs in your model have id="id" (duplicate id attributes)
There is no need to pass the name and id to the helper (and in fact a minor typo passing the name means binding will fail). Instead use the ModelMetadata to generate the correct attributes. In addition, ex is not a valid attribute and its not clear what you are trying to achieve with tb.Attributes.Add("ex", expression.ToString()); but it should be removed.
public static IHtmlString Images<TModel,TValue>(this HtmlHelper<TModel> helper,System.Linq.Expressions.Expression<Func<TModel, TValue>> expression)
{
string name = ExpressionHelper.GetExpressionText(expression);
string id = HtmlHelper.GenerateIdFromName(name);
TagBuilder tb = new TagBuilder("input");
// tb.Attributes.Add("ex", expression.ToString());
tb.MergeAttribute("name", name);
tb.MergeAttribute("id", id);
tb.MergeAttribute("type", "file");
tb.MergeAttribute("accept", "Image/*");
return new MvcHtmlString(tb.ToString(TagRenderMode.SelfClosing));
}

AngularJS service's POST to web api controller results in Object properties being null

I am trying to form an object and post it to the web api controller. The action looks like this:
public HttpResponseMessage Post(Contacts contact)
{
db.Add(contact);
db.SaveChanges();
var response = new HttpResponseMessage(HttpStatusCode.OK);
return response;
}
AngularJS controller posts like this:
$scope.submitData = function submitData() {
console.log($scope.contact);
$http.post('api/Contacts', $scope.contact);
}
The problem is that the data which needs to be posted has properties which are shown as Object in the console (Addresses in this example).
After the post all the Addresses count is null on the web api controller side, but not the other plain properties have the corresponding value.
How can I pass the Objects to be readable on the web api side?
Contacts model:
public partial class Contacts
{
public Contacts()
{
this.Addresses = new HashSet<Addresses>();
this.Emails = new HashSet<Emails>();
this.PhoneNumbers = new HashSet<PhoneNumbers>();
this.Tags = new HashSet<Tags>();
}
public int ContactID { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public virtual ICollection<Addresses> Addresses { get; set; }
public virtual ICollection<Emails> Emails { get; set; }
public virtual ICollection<PhoneNumbers> PhoneNumbers { get; set; }
public virtual ICollection<Tags> Tags { get; set; }
}
How i fill the addresses object:
<fieldset class="container" ng-repeat="i in getAddress() track by $index">
<legend>Address {{$index + 1}}</legend>
<label>Street:</label>
<input ng-model="contact.Addresses[$index].Street" class=" form-control" type="text" /><br />
<label>Number:</label>
<input ng-model="contact.Addresses[$index].Number" class="form-control" type="text" /><br />
<label>City:</label>
<input ng-model="contact.Addresses[$index].City" class="form-control" type="text" /><br />
<label>Country:</label>
<input ng-model="contact.Addresses[$index].Country" class="form-control" type="text" /><br />
</fieldset>

Resources