Properly receive a nested object via post - asp.net

I'm trying to send a complex object as a form object over to a mvc controller. However I just receive a new object with default values.
Here's the object (just a bit trimmed to make it simpler for the example)
public class AddProjectPopupModel
{
public long SelectedCountryId;
public Project ResultProject { get; set; }
}
public class Project
{
public long Number;
public string Name;
}
And here's how I create the form:
#using (Html.BeginForm("AddProjectResult", "Popups", FormMethod.Post, new { id = "addProjectForm"}))
{
#Html.EditorFor(model => model.ResultProject.Number, new { htmlAttributes = new { Id = "number", Class = "validate", Value = 0 } })
#Html.EditorFor(model => model.ResultProject.Name, new { htmlAttributes = new { Id = "name", Class = "validate" } })
}
Now I have a button which calls the following javascript:
var form = $("#addProjectForm");
var data = form.serialize();
var url = form.attr('action');
$.ajax({
type: "POST",
url: url,
data: data,
success: function(result) {
debugger;
}
});
And the controller:
[HttpPost]
public ActionResult AddProjectResult(AddProjectPopupModel model)
{
return Json(new { Success = true });
}
I've also tried to change the controller parameters to:
public ActionResult AddProjectResult(long SelectedCountryId, Project ResultProject)
And here the SelectedCountryId gets filled properly, but not the Project.
I'd love to use the whole AddProjectPopupModel as parameter and not it's specific values.
However I can't figure out to do it properly.
Fiddler output for the call:
Debugger values in controller:

Your problem is that in your project object you're using fileds
public class Project
{
public long Number;
public string Name;
}
and they should be properties so they can be navigated to
public class Project
{
public long Number { get; set; }
public string Name { get; set; }
}
This should work
I recommend reading Model Binding for more info

Related

Populate a select list ASP.NET Core MVC

I'm busy with an ASP.NET Core MVC application, and I'm trying to populate a drop down list. I've created a view model and I have added a method to my StoresController that returns a list of stores that I want to display in a dropdown. I've been working off some online tutorials as I'm very new to asp.
View model:
public class StoreListViewModel
{
public List<StoreList> StoreList { get; set; } = new List<StoreList>();
}
public class StoreList
{
public string StoreId { get; set; } = null!;
public string StoreName { get; set; } = null!;
}
StoresController:
public IActionResult LoadStoreList()
{
if (ModelState.IsValid)
{
var storeList = new StoreListViewModel().StoreList.Select
(x => new SelectListItem { Value = x.StoreId, Text = x.StoreName }).ToList();
ViewBag.Stores = storeList;
}
return NotFound();
}
I'm trying to use ViewBag to call my LoadStoreList() method.
<select name="storeList" class="form-control" asp-items="#(new SelectList(ViewBag.Stores, "Value", "Text"))"></select>
When I load my page I get the following error
Value cannot be null. (Parameter 'items')
The page I need the dropdown list on is my CreateUser.cshtml which is bound to my UserModel and has a UsersController. The method I have created for listing the stores is in my StoresController which is bound to my StoresModel. So I'm not sure if that's causing the issue.
I've been battling with this for days, if someone could help me get this working or show me a better method, that would be great.
*Edit
The UserIndex() method is the first method that fires when my users page opens, do I call the LoadStoreList() method from there ?
UserController
public async Task<IActionResult> UsersIndex()
{
return _context.UsersView != null ?
View(await _context.UsersView.ToListAsync()) :
Problem("Entity set 'ApplicationDbContext.Users' is null.");
}
I'm trying to use ViewBag to call my LoadStoreList() method.
ViewBag cannot be used to call any method. You just need set value for ViewBag in the method which renders your show dropdownlist's page.
From your description, you said the page you need the dropdown list on is CreateUser.cshtml. Assume that you render the CreateUser.cshtml page by using CreateUser action.
CreateUser.cshtml:
<select name="storeList" class="form-control" asp-items="#(new SelectList(ViewBag.Stores, "Value", "Text"))"></select>
Controller:
public class YourController : Controller
{
private readonly YourDbcontext _context;
public YourController(YourDbcontext context)
{
_context = context;
}
[HttpGet]
public IActionResult CreateUser()
{
var storeList = _context.StoreLists.Select
(x => new SelectListItem { Value = x.StoreId , Text = x.StoreName }).ToList();
ViewBag.Stores = storeList;
return View();
}
}
YourDbcontext should be something like:
public class YourDbcontext: DbContext
{
public YourDbcontext(DbContextOptions<MvcProjContext> options)
: base(options)
{
}
public DbSet<StoreList> StoreLists{ get; set; }
}
Dont use viewbag for storing list data. Make your view page model including List, for example:
public class UserCreationViewModel{
public int Id{ get; set; }
public string Name { get; set; }
// Any other properties....
public List<StoreList> StoreList { get; set; }
}
in your controller YourController:
[HttpGet]
public IActionResult CreateUser()
{
var storeList = new StoreListViewModel().StoreList.Select
(x => new SelectListItem { Value = x.StoreId, Text = x.StoreName }).ToList();
UserCreationViewModel model=new UserCreationViewModel{
StoreList = storeList
};
return View("createUserViewName", model);
}
in createUserViewName:
#Html.DropDownList("StoreId", new SelectList(Model.StoreList, "StoreId", "StoreName"), "Select", new { #class = "form-control" })
or
<select class="form-control" asp-for="#Model.StoreId" asp-items="#(new SelectList(Model.StoreList, "StoreId", "StoreName"))">
<option value="-1">Select</option>
</select>

how to send file along with data in formdata in angular 10

i want to send data in FormData along side with Files in the same object.
i have an object
var dataForm : FormData = new FormData();
var objectToSend : any = {};
objectToSend.object1 = {
Name:'Name',
ID: 1
};
objectToSend.Arr = [1,2,3];
i 've found out how to put a file in the FromData
this.dataForm.append('file', <File>files[0], (<File>files[0]).name);
but when putting the data object in it the same way i put the file like this ...
var stringfiedObejct = JSON.stringify(objectToSend);
this.dataForm.append('data', new Blob([stringfiedObejct], { type: 'application/json' }));
and the call like
this.Http.post(`apiPath`, this.dataForm, { reportProgress: true, observe: 'events' })
.subscribe(event => {
});
it generate error 415 Unsupported Media although the api method has the same definition for the object
public class DataObject
{
public int ID {get;set;}
public string Name {get;set;}
}
public class RequestParams
{
public List<int> Arr {get;set;}
public DataObject object1 {get;set;}
}
and the api is ...
[HttpPost("uploadFile"), DisableRequestSizeLimit]
public IActionResult Upload(RequestParams param)
{
var file = Request.Form.Files[0];
return Ok();
}
although the file is received in the api, but as soon i put the object in the FormData it generate that error
If you want to pass object in formdata,you can do like this:
DemoModel:
public class DemoModel
{
public IList<IFormFile> Images{ get; set; }
public DataObject object1 {get;set;}
}
pass object to FormData:
var pdata = new FormData();
pdata.append('object1.Name', 'Name');
pdata.append('object1.ID', 1);

How to bind bropdown list in Razor View (If view is not bound with any model)

Can anybody suggest me how bind a dropdown list in MVC Razor view. I am using MVC 4. I have a view that is not bound with any model class.
public class Util {
public List<EmployeeType> GetEmpTypes() {
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
}
public class EmployeeType {
public int ID { get; set; }
public string Text { get; set; }
}
I have this sample code. I am new to MVC Now after this I don't know how to bind the collection returned by GetEmployeeTypes() Method to a dropdown list
Your class with method
public class Util {
public List<EmployeeType> GetEmpTypes() {
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
}
Your model class with properties
public class EmployeeType {
public int ID { get; set; }
public string Text { get; set; }
}
This is sample action
public ActionResult ViewName()
{
Util xxx=new Util();
List<SelectList> SelectedItems =new List<SelectList>();
List<EmployeeType> items =xxx.GetEmpTypes();
foreach (var t in items )
{
SelectListItem s = new SelectListItem();
s.Text = t.Text;
s.Value = t.ID;
SelectedItems.Add(s);
}
ViewBag.xxxxx= SelectedItems;
return view();
}
In View
#Html.DropDownList("xxxxx", new SelectList(ViewBag.xxxxx, "Text", "Value"))
This above code just like a key, i don't tested for that code ran successfully. you can get some idea for how to bind dropdown from my code.
I had a Class like this to get all EmployeeTypes
public class Util
{
public List<EmployeeType> GetEmpTypes()
{
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
}
public class EmployeeType
{
public int ID { get; set; }
public string Text { get; set; }
}
In Controller I have written code to get the List of Employee Types
Util obj = new Util();
var v = obj.GetEmpTypes();
ViewBag.EmployeeTypes = v;
return View();
In the View I have written code to bind dropdown.
#Html.DropDownList("EmployeeTypes",new SelectList(ViewBag.EmployeeTypes,"ID","Text"));
Thanks #Ramesh Rajendran ( Now I understood the concept to bind dropdown)
*strong text*you should create the model selectlist like here:
public static List<EmployeeType> GetEmpTypes() {
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
public static SelectList GetMyEmpTypes
{
get { return new SelectList(GetEmpTypes(), "ID", "Text"); }
}
then you access this method in dropdown list like
#Html.DropDownList("Name",yourProjectNameSpace.Util.GetMyEmpTypes())
when you will submit your form then it value bidden with Name get post to controller.
it is not necessary to bind with model class.you can receive the value on controller with the name that you have given in view like:
#Html.DropDownList("Name",yourProjectNameSpace.YourClass.GetEmpTypes())
Now you can recive the name value at controller like:
public ActionResult test(String Name)
{
return view();
}
and make your method static i.e GetEmpTypes() so that you can access it from view.

How to post JSON data to SQL using ajax post & knockout

I have a pretty straightforward view model:
var ProjectViewModel = {
ProjectName: ko.observable().extend({ required: "" }),
ProjectDescription: ko.observable().extend({ required: "" }),
ProjectStartDate: ko.observable(),
ProjectEndDate: ko.observable()
};
I want to save this data that is located in my viewmodel to my SQL server.
I have a class defining this View Model in my Server Side Code:
public class Projects
{
public string ProjectName { get; set; }
public DateTime ProjectStartDate { get; set; }
public DateTime ProjectEndDate { get; set; }
public string ProjectDescription { get; set; }
}
I also have this web method to receive the code:
[WebMethod]
public bool SaveProject(string[] JSONDATA)
{
TaskNinjaEntities entities = new TaskNinjaEntities();
foreach (var item in JSONDATA)
{
Console.WriteLine("{0}", item);
}
return true;
}
And finally I have this POST that does not want to send the data to the server:
function SaveMe() {
var data = ko.toJSON(ProjectViewModel);
$.post("CreateProject.aspx/SaveProject", data, function (returnedData) {
});
}
I get nothing from the returned data in this post method, also added breakpoint in server side code, and it doesn't hit it at all. My URL is correct and the Viewmodel converts to JSON without hassle.
Make the web method static.
[WebMethod]
public static bool SaveProject(string[] JSONDATA)
{
TaskNinjaEntities entities = new TaskNinjaEntities();
foreach (var item in JSONDATA)
{
Console.WriteLine("{0}", item);
}
return true;
}

populate a select in ASP.net MVC3 with Data in the database using nHibernate

I need to populate the data which is in the database fields using nHibernate mapping for a select in ASP.net MVC3... Please send me a sample code of how to do it..
Regards
Srividhya
You could start by defining a view model:
public class MyViewModel
{
public string SelectedItemId { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
then a controller which will populate this view model (hardcode some values at the beginning just to make sure that it works and you have a mockup screens to show to your users):
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
Items = new[]
{
new SelectListItem { Value = "1", Text = "item 1" },
new SelectListItem { Value = "2", Text = "item 2" },
new SelectListItem { Value = "3", Text = "item 3" },
}
};
return View(model);
}
}
and finally a view:
#model MyViewModel
#Html.DropDownListFor(
x => x.SelectedItemId,
new SelectList(Model.Items, "Value", "Text")
)
The next step could consist into defining a model, setting the mapping for this model, a repository allowing you to fetch the model with NHibernate and finally call this repository in the controller action and map the returned model to the view model I used in the example:
Model:
public class Item
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
Repository:
public interface IItemsRepository
{
IEnumerable<Item> GetItems();
}
and now the controller becomes:
public class HomeController : Controller
{
private readonly IItemsRepository _repository;
public HomeController(IItemsRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
var items = _repository.GetItems();
var model = new MyViewModel
{
Items = items.Select(item => new SelectListItem
{
Value = item.Id.ToString(),
Text = item.Name
})
};
return View(model);
}
}
OK, we are making progress little by little. Now you can write unit tests for this controller action.
The next step would be to implement this repository:
public class ItemsRepositoryNHibernate : IItemsRepository
{
public IEnumerable<Item> GetItems()
{
throw new NotImplementedException(
"Out of the scope for this question. Checkout the NHibernate manual"
);
}
}
and the last step is to instruct your dependency injection framework to pass the correct implementation of the repository to the HomeController. For example if you use Ninject all you need to do is to write a module that will configure the kernel:
public class RepositoriesModule : StandardModule
{
public override void Load()
{
Bind<IItemsRepository>().To<ItemsRepositoryNHibernate>();
}
}

Resources