Troubles with MVC - c#

I am freshman in MVC, so I have some problems. I want to create Create Form, where I can insert some information such as Country, Region etc. and after to Serialize it to the file. But my Create Method get object wich don't have any indormation. So where I did mistake?
[HttpPost] // This is my Method which must Serialize class Address
public ActionResult Create(Address address)
{
if (ModelState.IsValid)
{
// Размещаем в XML данные
System.Xml.Serialization.XmlSerializer writer =
new System.Xml.Serialization.XmlSerializer(typeof(Address));
System.IO.StreamWriter file = new System.IO.StreamWriter(#"c:\MvcApp.xml");
writer.Serialize(file, address);
file.Close();
return RedirectToAction("Index");
}
return View(address);
}
This is my VIEW FILE
#model WorkWithAddresses.Models.Address
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Address</legend>
<div class="editor-label">
#Html.LabelFor(model=>model.country, "Country")
</div>
<div class="editor-field">
#Html.EditorFor(model=>model.country)
#Html.ValidationMessageFor(model=>model.country)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.region, "Region")
<div>
<div class="editor-field">
#Html.EditorFor(model=>model.region)
#Html.ValidationMessageFor(model=>model.region)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.locality,"Locality")
</div>
<div class ="editor-field">
#Html.EditorFor(model=>model.locality)
#Html.ValidationMessageFor(model=>model.locality)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.locality,"Street")
</div>
<div class ="editor-field">
#Html.EditorFor(model=>model.street)
#Html.ValidationMessageFor(model=>model.street)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.locality,"House")
</div>
<div class ="editor-field">
#Html.EditorFor(model=>model.houseNumber)
#Html.ValidationMessageFor(model=>model.houseNumber)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.locality,"Building")
</div>
<div class ="editor-field">
#Html.EditorFor(model=>model.buildingNumber)
#Html.ValidationMessageFor(model=>model.buildingNumber)
</div>
<div class ="editor-label">
#Html.LabelFor(model=>model.locality,"Apartment")
</div>
<div class ="editor-field">
#Html.EditorFor(model=>model.apartmentNumber)
#Html.ValidationMessageFor(model=>model.apartmentNumber)
</div>
<p>
<input type="submit" value="Create"/>
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List","Index")
</div>
// This is my class which I want to Serialize after user put information
[XmlRoot("Address")]
public class Address
{
#region Constructors
public Address()
{
}
#endregion
#region Public Member Variables
[XmlElement("AddressId")]
public int addressId; // Id адреса
[XmlElement("Country")]
public string country; // Страна
[XmlElement("Region")]
public string region; // Регион
[XmlElement("Locality")]
public string locality; // Населенный пункт
[XmlElement("Street")]
public string street; // Улица
[XmlElement("HouseNumber")]
public string houseNumber; // Номер дома
[XmlElement("BuildingNumber")]
public string buildingNumber; // Номер корпуса
[XmlElement("ApartmentNumber")]
public string apartmentNumber; // Номер квартиры
[XmlElement("Description")]
public Description description; // Описание адреса
#endregion
}
}

The View and the controller action code all look fine to me. The issue will be in the address class in the model. Mvc needs to have properties to deserialise the webforms post to.
public string Country { get; set; }
You should name these using title case for convention but it would still work if you kept them lowercase.

Related

ASP.NET MVC View needs to display data from a certain model and at the same time take input data for another model

I have a View which uses a dynamic object to pull data from multiple models declared in the ViewModel. However, within the same model I am trying to take user input via a form. The data is correctly displayed for the 2 models which are also part of the dynamic object. But I am UNSUCCESSFUL getting the form input, because I keep getting the error that the dynamic object is not accessible.[And this is for the form only.]
Here is how the View looks like
#model dynamic
#using ActionAugerMVC.ViewModels
#addTagHelper "*,Microsoft.AspNetCore.Mvc.TagHelpers"
<div class="course__title">
#Model.item.PageTitle
</div>
<p class="course__desc">
#Html.Raw(Model.item.PageText)
</p>
<div class="event__price">
<h3>#Model.item.NoticeTitle</h3>
<p>#Model.item.NoticeNeedItem</p>
<button type="submit" class="btn btn-accent">
Get A Quote Now
</button>
</div>
<h3 class="course_desc__title">Other Services</h3>
<ul class="course_requirements__list multi-column">
#foreach (var link in Model.data)
{
<li><i class="ion-android-arrow-forward"></i> #Html.ActionLink((string)link.PageTitle, "Page", "Plumbing", new { id = link.ID, url = link.PageURL }) </li>
}
</ul>
<div class="sidebar__item">
<p class="subheading">Instant Quote Request</p>
<form class="register__form" role="form" asp-controller="Plumbing" asp-action="Page" method="post">
<div class="text-danger" asp-validation-summary="All"></div>
<div class="form-group">
<label class="sr-only">Full Name </label>
<input asp-for="#Model.quote.FullName" type="text" class="form-control" placeholder="Full name">
</div>
<div class="form-group">
<label class="sr-only">Your phone</label>
<input asp-for="#Model.quote.Phone" type="tel" class="form-control" placeholder="Your phone">
<span asp-validation-for="#Model.quote.Phone" class="text-danger"></span>
</div>
<div class="form-group">
<label class="sr-only">E-mail</label>
<input asp-for="#Model.quote.Email" type="email" class="form-control" placeholder="E-mail">
<span asp-validation-for="#Model.quote.Email" class="text-danger"></span>
</div>
<div class="form-group">
<label class="sr-only">Your Message</label>
<input asp-for="#Model.quote.Message" type="text" class="form-control" placeholder="Your Message">
</div>
<input type="submit" value="Get a Quote Now" class="btn btn-accent btn-block">
</form>
</div> <!-- .sidebar__item -->
And here is how the controller looks like :-
public class PlumbingController : Controller
{
private readonly ActionAugerDataContext actionAugerDbContext;
private readonly UnitOfWork unitOfWork;
private readonly PlumbingPageViewModel plumbingViewModel;
public PlumbingController(ActionAugerDataContext context)
{
actionAugerDbContext = context;
unitOfWork = new UnitOfWork(actionAugerDbContext);
plumbingViewModel = new PlumbingPageViewModel(unitOfWork);
}
// GET: /<controller>/
public IActionResult Index()
{
var data = plumbingViewModel.PlumbingContent;
return View(data);
}
[HttpGet]
[Route("plumbing/calgary-{url}")]
public IActionResult Page(int ID, string url)
{
dynamic Page = new ExpandoObject();
Page.item = unitOfWork.ContentRepository.GetById(ID);
Page.data = plumbingViewModel.PlumbingContent;
Page.cities = plumbingViewModel.Cities;
// Page.quote = plumbingViewModel.Quote;
return View(Page);
}
[HttpPost]
public IActionResult Page(Quote quote)
{
return View();
}
}
Here is the View Model :-
public class PlumbingPageViewModel
{
public IEnumerable<Content> PlumbingContent { get; set; }
public IEnumerable<Cities> Cities { get; set; }
public Quote Quote { get; set; }
public PlumbingPageViewModel(UnitOfWork unitOfWork)
{
PlumbingContent = unitOfWork.ContentRepository
.GetAll()
.Where(d => d.Section == "Plumbing")
.Where(c => c.City == "Calgary");
Cities = unitOfWork.CitiesRepository
.GetAll()
.Where(c => c.HomeCity == "Calgary");
}
}
And here is the model class for the form.
public class Quote
{
public int ID { get; set; }
public string FullName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string City { get; set; }
public string Message { get; set; }
}
you can't you use dynamic model ( #model dynamic) for building your form with HtmlHelper
If you want Post form you should specific model.
Hope you this will you.

mvc c# file upload as byte array

I have to upload files and other data in a single submit of UploadFile.cshtml form
I have a base class which is the input of mvc action in home controller.
My base class, mvc action method and cshtml part with Razor script is given below
I have to get the file as byte array in the mvc action while submitting the UploadFile.cshtml form
My Base class
public class FileUpload
{
public string Name {get;set;}
public int Age {get;set;}
public byte[] Photo {get;set;}
}
MyMVCAction
[HttpPost]
public void UploadFile(FileUploadobj)
{
FileUploaddata=obj;
}
Mycshtmlform
#modelMVC.Models.FileUpload
#using(Html.BeginForm("UploadFile","Home",FormMethod.Post))
{
<fieldset>
<legend>File Upload</legend>
<div class="editor-label">
#Html.LabelFor(model=>model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model=>model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model=>model.Age)
</div>
<div class="editor-field">
#Html.EditorFor(model=>model.Age)
</div>
<div class="editor-label">
#Html.Label("UploadPhoto");
</div>
<div class="editor-field">
<input type="file" id="photo" name="photo"/>
</div>
<p>
<input type="submit" value="Create"/>
</p>
</fieldset>
}
I think better achieve it like this:
[HttpPost]
public ActionResult UploadFile(FileUpload obj)
{
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
obj.Photo = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}
//return some action result e.g. return new HttpStatusCodeResult(HttpStatusCode.OK);
}
I hope it helps.

Multiple forms issue

I have an object passed to an "Edit" controller. The object is a "Component" which can also have "Component Properties" added to it: Manufacturer, Size, etc. I want to be able to add those attributes on the same page as the object's Edit view.
I have 2 forms. The first one functions correctly to edit the model.
The second one posts to the "Create" method of the ComponentPropertyValueController, but the only value that passes to the object parameter is the value entered (such as the manufacturer). The Parent object attributes needed to be associated with the added "Component Properties" are 0's and null.
What I have done is tried to instantiate a new ComponentPropertyValue object and set the id to the parent id. I also tried setting the parent object to the current view model.
I cannot figure out how to make the new ComponentPropertyValue object passed to the Create controller belong to the parent Component when it posts.
Here is a picture of the form. The form looks fine. It has the proper drop downs and seems to function correctly.
Screenshot
Picture of Entity Model
The model is purposely Generic. Allowing to add an type of thing and add attributes to them.
"Component" Controller Code:
//
// GET: /Components/Edit/5
public ActionResult Edit(int id = 0)
{
Component component = db.Components.Find(id);
if (component == null)
{
return HttpNotFound();
}
ViewBag.ComponentPropertyId = new SelectList(db.ComponentProperties, "Id", "Property");
ViewBag.ComponentTypeId = new SelectList(db.ComponentTypes, "Id", "Type", component.ComponentTypeId);
return View(component);
}
Razor View:
#model removed.com.Models.Component
#using removed.com.Models
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Component</legend>
#Html.HiddenFor(model => model.Id)
<div class="editor-label">
#Html.LabelFor(model => model.ComponentTypeId, "ComponentType")
</div>
<div class="editor-field">
#Html.DropDownList("ComponentTypeId", String.Empty)
#Html.ValidationMessageFor(model => model.ComponentTypeId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<h2>Add Property</h2>
#{
ComponentPropertyValue componentPropertyValue = new ComponentPropertyValue() { Component = Model, ComponentId = Model.Id} ;
}
#using (Html.BeginForm("Create", "ComponentPropertyValue", FormMethod.Post, componentPropertyValue))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>ComponentPropertyValue</legend>
<div class="editor-label">
#Html.LabelFor(x => componentPropertyValue.ComponentPropertyId, "ComponentProperty")
</div>
<div class="editor-field">
#Html.DropDownList("ComponentPropertyId", String.Empty)
#Html.ValidationMessageFor(x => componentPropertyValue.ComponentPropertyId)
</div>
<div class="editor-label">
#Html.LabelFor(x => componentPropertyValue.Value)
</div>
<div class="editor-field">
#Html.EditorFor(x => componentPropertyValue.Value)
#Html.ValidationMessageFor(x => componentPropertyValue.Value)
</div>
<p>
<input type="submit" value="Add" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
I have also tried to add hidden inputs, and here is the html for the form:
<form Component="" ComponentId="" ComponentProperty="" ComponentPropertyId="0" Id="0" Value="" action="/ComponentPropertyValue/Create" method="post"> <fieldset>
<legend>ComponentPropertyValue</legend>
<input id="ComponentId" name="ComponentId" type="hidden" value="36" />
36 is the correct id for the record. but it is never passed to the controller.
If after instantiating, I set the ComponentId:
#{
ComponentPropertyValue componentPropertyValue = new ComponentPropertyValue() { ComponentId = Model.Id };
}
#using (Html.BeginForm("Create", "ComponentPropertyValue", FormMethod.Post, componentPropertyValue))
The form is generated with the value set. Yet it still never reaches the controller.
<form Component="" ComponentId="36" ComponentProperty="" ComponentPropertyId="0" Id="0" Value="" action="/ComponentPropertyValue/Create" method="post">
My view model for the two interacting classes:
public partial class Component
{
public Component()
{
this.ComponentPropertyValues = new HashSet<ComponentPropertyValue>();
this.ComponentVideos = new HashSet<ComponentVideo>();
}
public int Id { get; set; }
public int ComponentTypeId { get; set; }
public string Name { get; set; }
public virtual ICollection<ComponentPropertyValue> ComponentPropertyValues { get; set; }
public virtual ComponentType ComponentType { get; set; }
public virtual ICollection<ComponentVideo> ComponentVideos { get; set; }
}
public partial class ComponentPropertyValue
{
public int Id { get; set; }
public int ComponentPropertyId { get; set; }
public int ComponentId { get; set; }
public string Value { get; set; }
public virtual ComponentProperty ComponentProperty { get; set; }
public virtual Component Component { get; set; }
}

how to add multiple rows in mvc 4 and razor engine

I am creating finance application in mvc 4 and razor. in that there is one module Journal.
One Journal can have multiple entries. and Journal can not be created without Journal Entry.
Following is my model
using Sms.Core;
using System;
using System.Collections.Generic;
namespace Sms.CoreSociety
{
public class Journal : BaseClass
{
public Journal()
{
this.JournalEntries = new List<JournalEntry>();
}
public virtual string VoucherNo { get; set; }
public virtual DateTime VoucherDate { get; set; }
public string VoucherDateView
{
get
{
return VoucherDate.ToShortDateString();
}
}
public IList<JournalEntry> JournalEntries { get; set; }
public IList<Ledger> Accounts { get; set; }
public double TotalAmount
{
get
{
double sum = 0;
if (JournalEntries != null && JournalEntries.Count > 0)
foreach (var journal in JournalEntries)
sum = journal.Principal + journal.Interest + sum;
return sum;
}
}
}
}
Following is my View
#model Sms.CoreSociety.Journal
#{
ViewBag.Title = "Create";
}
#using (Html.BeginForm(null, null, FormMethod.Post, new Dictionary<string, object>() { { "class", "form-horizontal" }, { "id", "document" } }))
{
#Html.ValidationSummary(true)
<fieldset>
<div class="row">
<div class="span1">
<label>
Voucher No</label>
</div>
<div class="span5">
#Html.TextBoxFor(model => model.VoucherNo)
</div>
</div>
<div class="row">
<div class="span1">
<label>
Voucher Date</label>
</div>
<div class="span5">
#Html.TextBoxFor(model => model.VoucherDate)
</div>
</div>
<div class="row">
<div class="span1">
<label>
Amount</label>
</div>
<div class="span5">
#Html.TextBoxFor(model => model.TotalAmount)
</div>
</div>
#Html.TextBox("JournalEntries[0].AccountName", Model.JournalEntries.FirstOrDefault().AccountName)
#Html.TextBox("JournalEntries[0].DebitCredit", Model.JournalEntries.FirstOrDefault().DebitCredit)
#Html.TextBox("JournalEntries[0].Interest", Model.JournalEntries.FirstOrDefault().Interest)
#Html.TextBox("JournalEntries[0].Narration", Model.JournalEntries.FirstOrDefault().Narration)
<input type="submit" value="Save" class="btn" id="submit" />
#if (Model.Id != new Guid())
{
<div style="float: right">
<a class="btn btn-danger" href='#Url.Action("Delete")/#Model.Id' aria-hidden="true">
Delete</a>
</div>
}
</fieldset>
}
<h4>
Journal Entry</h4>
<p>
#Html.ActionLink("Add Entry", "JournalEntry");
Now I am able to get the Journal as well as Single Journal Entry. But my problem is I am not able to make Multiple journal entry.
This is what i am looking for but in MVC 4 and razor without knockout.js
To achieve your goal, you need to do some extra works by jquery, ajax and partial views.
A brief example is here. A full howto is here.

MVC3/C#/Razor/EF handling data from multiple partial 'create views'

For registering a new customer I have several partials on my view which refer to corresponding tables in my database.
Primary keys are identity fields, that's why no IDs on the view. To insert a new customer I need to insert 3 occurrences of address(visiting, postal and contact person's), then insert a row for contract, contact_person(with using addressId from one of already inserted addresses) and finally proceed with inserting a new customer which will contain foreign keys referencing to just inserted visiting and postal addresses, contract and contact person.
Could you recommend the best/easiest way to pass the data from these partial views as objects to CustomerController and handle the objects there please?
Links to examples of handling similar situations will be also highly appreciated.
Image of my page:
http://i1345.photobucket.com/albums/p673/swell_daze/customer_registration_zps563341d0.png
Image of tables:
http://i1345.photobucket.com/albums/p673/swell_daze/tables_zpsc60b644a.png
View code:
#model CIM.Models.customer
<h2>Register new customer</h2>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
<legend>New customer registration</legend>
<fieldset class="span3">
<legend>Basic information</legend>
<div class="editor-label">
#Html.LabelFor(model => model.name, "Name")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.name)
#Html.ValidationMessageFor(model => model.name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.groupId, "Customer group")
</div>
<div class="editor-field">
#Html.DropDownList("groupId", String.Empty)
#Html.ValidationMessageFor(model => model.groupId)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.status, "Status")
</div>
<div class="editor-field">
#Html.DropDownList("status")
#Html.ValidationMessageFor(model => model.status)
</div>
</fieldset>
<fieldset class="span3">
<legend>Visiting address</legend>
<div>
#{
Html.RenderPartial("AddressPartial");
}
</div>
</fieldset>
<fieldset style="width:270px">
<legend>Postal address</legend>
<div>
#{
Html.RenderPartial("AddressPartial");
}
</div>
</fieldset>
<fieldset class="span3">
<legend>Contract</legend>
<div>
#{
Html.RenderPartial("ContractPartial");
}
</div>
</fieldset>
<fieldset class="span3" style="width:540px">
<legend>Contact person</legend>
<div>
#{
Html.RenderPartial("ContactPersonPartial");
}
</div>
<p>
<input type="submit" class="btn btn-success" value="Submit" style="margin-right:1em"/>
#Html.ActionLink("Cancel", "Index", "Customer", new {#class="btn btn-danger", #type="button"})
</p>
</fieldset>
</fieldset>
}
you can wrap your view data in a viewmodel, then when you submit your data it will be mapped to your viewmodel, something like this:
Create a viewmodel:
public class MyViewModel
{
public string name { get; set; }
public string someprop1 { get; set; }
public string someprop2 { get; set; }
public MyAddress visitingaddress { get; set; }
public MyAddress postaladdress { get; set; }
public MyContactAddress contactaddress { get; set; }
}
public class MyAddress
{
public string town { get; set; }
public string street { get; set; }
public string housenumber { get; set; }
public string postalcode { get; set; }
}
public class MyContactAddress : MyAddress
{
public string firstname { get; set; }
public string lastname { get; set; }
public string email { get; set; }
public string phonenumber { get; set; }
}
Create your view just like you have done but by using your viewmodel instead of the model you are using now (CIM.Models.customer), and then in your partials, for example in the postal address partial view do something like this:
.......
#Html.EditorFor(x => x.postaladdress.town)
......
Create your controller actions by using your viewmodel:
public ActionResult Index()
{
MyViewModel vm = new MyViewModel();
//doing something here....
return View(vm);
}
[HttpPost]
public ActionResult Index(MyViewModel vm)
{
//save your data, here your viewmodel will be correctly filled
return View(vm);
}
hope this helps

Categories