Pass Lists to MVC controller Action using POSTMan chrome extention - asp.net-mvc

I am using Postman Chrome extension to test my MVC service API.
The model that I pass to the controller looks as follows:
public class ActivateBenefitRequestModel
{
public int BenefitID { get; set; }
public int MemberID { get; set; }
public string Token { get; set; }
public List<AdditionalBenefitField> BenefitAdditionalFields { get; set; }
}
with
public class AdditionalBenefitField
{
public int BenefitFieldId { get; set; }
public string Value { get; set; }
}
How should I go about passing in the BenefitAdditionalFields List ?
Is it even possible?

Assuming that all you're doing is building a POST request string (not familiar with the extension), I believe you can just format your request to specify individual list elements indexed with URL-encoded square brackets:
...&AdditionalBenefitFields%5B0%5D.BenefitFieldId=1&AdditionalBenefitFields%5B0%5D.Value=Foo
&AdditionalBenefitFields%5B1%5D.BenefitFieldId=2&AdditionalBenefitFields%5B1%5D.Value=Bar&...
This is how a POST request for a list of complex types looks in one of our MVC3 projects and I'm pretty sure we don't do anything special with it.

So I got it and it's pretty easy:
Just set separate text values in your form data in the PostMan extention
BenefitAdditionalFields[0].BenefitFieldId
BenefitAdditionalFields[0].Value
BenefitAdditionalFields[1].BenefitFieldId
BenefitAdditionalFields[1].Value

Related

How do I send a state-only object containing another state-only object to a Web API controller?

I am trying to send a simple object (AjaxSubmission) from a form to a Web API controller used to edit tables.
AjaxSubmission always has the same fields. One field, "data" refers to another simple object with accessors for the specific table (Employees or Vendors examples below).
public class AjaxSubmission
{
public string action { get; set; }
public string table { get; set; }
public string id { get; set; }
// ...
//// The following may be any other custom class
public Employees data { get; set; } // Could be Vendors or whatever
}
// Stored in AjaxSubmission (or so I hope)
public class Employees
{
public string name { get; set; }
public float salary { get; set; }
public long id { get; set; }
}
// Stored in AjaxSubmission
public class Vendors
{
public string dba { get; set; }
public int accountNum { get; set; }
public int zipcode { get; set; }
}
My controller gets the data like so:
public EditorServerResponse Put(AjaxSubmission ajaxSubmission = null) {
// Handle the data
}
When I make "data" an Object or Dynamic, it shows up as an empty object. I can't "as" it to Employees or Vendors because it doesn't store anything.
I suspect this is a limitation of the serializer. MVC4 uses JSON.NET for JSON, but the data is sent as "Content-Type: application/x-www-form-urlencoded; charset=UTF-8".
I cannot easily change the way data is sent because that is how the Datatables editor plug-in does its business. I think it's a reasonable way to send data and a reasonable problem for .NET to be able to handle.
I can get the data I need if I make a distinct class for each data type that AjaxSubmission might contain, but each would be a duplicate other than one line of code. That horribly violates the DRY principle.
My question is: How can I send AjaxSubmission without Repeating Myself? Is .NET capable of such a thing?
Edit:
Fiddler says the data looks like:
action edit
table
id row_4
data[amu] 49
data[chemicalFormula] BF2
data[commonName] Boron difluoride
data[status] Y
data[notes]
The raw data is:
action=edit&table=&id=row_4&data%5Bamu%5D=49&data%5BchemicalFormula%5D=BF2&data%5BcommonName%5D=Boron+difluoride&data%5Bstatus%5D=Y&data%5Bnotes%5D=
(This is different from my simplified examples but similar)

How does one encode a model in x-www-form-urlencoded format so it can be consumed by an ASP.NET MVC action?

Assume I have an ASP.NET MVC 3 Controller that looks like this
public class MyController : Contoller
{
public ActionResult Edit(MyModel model)
{
/* doing some stuff with the model */
}
}
The model looks like this
public class MyModel
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public ThatModel Property1 { get; set; }
public List<ThisModel> BunchOfThisModel { get; set; }
}
public class ThatModel
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public string Property3 { get; set; }
public string Property4 { get; set; }
public string Property5 { get; set; }
public string Property6 { get; set; }
}
public class ThisModel
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
Does ASP.NET MVC or .NET (v4 is ok, v4.5 not) provide any built-in means to encode a model (say MyModel in this case) so that it can be sent to an action as form url encoded (aka x-www-form-urlencoded)? An example would be "property1=abc&property2=def". However, ASP.NET MVC has its own way to deal with nested models etc when decoding the request back to the model. Assume I'm simulating a browser using the WebRequest/WebResponse APIs provided since .NET 1.1.
In essence, I'd like to build up requests in tests to verify that
some data is excluded through binding, if needed
the anti forgery token is set, if needed
malicious data is handled accordingly
Note: ASP.NET Web API is not being used at this stage. Because I'm writing (integration) tests for an existing application, sending the model as JSON, XML or another alternative format isn't applicabile to the question.
I hope I've understood this question correctly, but provided you are 'POST'ing that data (from JSON?) then it is able to build up the model using a best-guess process.
Property names are matched, so if you sent (guessing the duplicate Property1 is actually Property3 here)
{
Property1="this",
Property2="that",
Property3={Property1="this3", ....},
BunchOfThisModel=[{Property1="bunchthis"},{....}]
}
This would populate your POCO with whatever names matched. If you left out a property (i.e. Property2) it would take on it's default(T) value.
Sending your object model in a GET request would be much more complicated, you could base64 the JSON string, and then parse it on server which is popular approach, but given it's a complex model POST might work best for your intentions.
You can also use a CustomBinder (a good article is here). You can also control which properties are bound to your POCO object by using the BindAttribute with the Exclude/Include options.
Hope I haven't missed the point and this proves useful :)

Creating dropdownlist in ASP.NET MVC3 using Razor view engine

I am creating a User Registration form in ASP.NET MVC3 using razor view engine. I am facing problem to create a dropdownlist for country. Country list come from xml file.
My project hierarchy is as follows
BusinessLayer -> User_Account -> Account_Registration.cs
This is a class library in which I want to create a Model for user registration. The code for user model is as follows
public class Account_Registration
{
public string User_Name { get; set; }
public string User_EmailID { get; set; }
public string User_Password { get; set; }
public string User_RePassword { get; set; }
public DateTime User_BirthDate { get; set; }
public enum_Gender User_Gender { get; set; }
public string User_Address { get; set; }
public string User_City { get; set; }
public string User_State { get; set; }
public IEnumerable<SelectListItem> User_Country { get; set; }
public string User_WebSite { get; set; }
public string User_Description { get; set; }
}
Now I want to know that where I should put country XML file and how can I create dropdownlist for XML file.
My Xml file is as follows
<countries>
<country code="AF" iso="4">Afghanistan</country>
<country code="AL" iso="8">Albania</country>
<country code="DZ" iso="12">Algeria</country>
</countries>
As I have to deploy this project on IIS so I want to know where should I put xml file so that I can access it in Account_Registration model which is in class library project and how to create dropdownlist for population countries.
Thanks
You probably shouldn't read xml file each time you render registration page. That would be one little bottleneck you'd have since hard drive operations are costly. I'd recommend reading it into memory (like at the application startup once and somewhere into the global variable, e.g. Countries).
For rendering your list, I'd recommend looking at the following article. Basically, it goes like this:
Html.DropDownList(“countries”, new SelectList(model.Countries), “CountryId”, “CountryName”))
you can create own extension for DropDown.
public static class GridExtensions
{
public static MvcHtmlString XmlDropDown(this HtmlHelper helper, string name, string value)
{
var document = XDocument.Parce(value);
var model = new List<SelectListItem>();
foreach(XElement element in document.Elements("countries/country"))
{
model.Add(new SelectListItem(){Text=element.Value, Value=element.Attribute("iso").Value})
}
return Html.DropDownList(name, model))
}
}
So, on view you can use
Html.XmlDropDown(“countries”, model.Countries)

MVC 4, Upshot entities cyclic references

I have a DbDataController which delivers a List of Equipment.
public IQueryable<BettrFit.Models.Equipment> GetEquipment() {
var q= DbContext.EquipmentSet.OrderBy(e => e.Name);
return q;
}
In my scaffolded view everything looks ok.
But the Equipment contains a HashSet member of EquipmentType. I want to show this type in my view and also be able to add data to the EquipmentType collection of Equipment (via a multiselect list).
But if I try to include the "EquipmentType" in my linq query it fails during serialisation.
public IQueryable<BettrFit.Models.Equipment> GetEquipment() {
var q= DbContext.EquipmentSet.Include("EquipmentType").OrderBy(e => e.Name);
return q;
}
"Object Graph for Type EquipmentType Contains Cycles and Cannot be Serialized if Reference Tracking is Disabled"
How can I switch on the "backtracking of references"?
Maybe the problem is that the EquipmentType is back-linking through a HashSet? But I do not .include("EquipmentType.Equipment") in my query. So that should be ok.
How is Upshot generating the model? I only find the EquipmentViewModel.js file but this does not contain any model members.
Here are my model classes:
public class Equipment
{
public Equipment()
{
this.Exercise = new HashSet<Exercise>();
this.EquipmentType = new HashSet<EquipmentType>();
this.UserDetails = new HashSet<UserDetails>();
}
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Picture { get; set; }
public string Link { get; set; }
public string Producer { get; set; }
public string Video { get; set; }
public virtual ICollection<EquipmentType> EquipmentType { get; set; }
public virtual ICollection<UserDetails> UserDetails { get; set; }
}
public class EquipmentType
{
public EquipmentType()
{
this.Equipment = new HashSet<Equipment>();
this.UserDetails = new HashSet<UserDetails>();
}
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Equipment> Equipment { get; set; }
public virtual ICollection<UserDetails> UserDetails { get; set; }
}
try decorating one of the navigation properties with [IgnoreDataMember]
[IgnoreDataMember]
public virtual ICollection<Equipment> Equipment { get; set; }
The model generated by upshot can be found on the page itself. In your Index view you will see the UpshotContext HTML helper being used (given that you are using the latest SPA version), in which the dataSource and model type are specified.
When the page is then rendered in the browser, this helper code is replaced with the actual model definition. To see that, view the source code of your page in the browser and search for a <script> tag that starts with upshot.dataSources = upshot.dataSources || {};
Check here for more info about how upshot generates the client side model.
As for the "backtracking of references", I don't know :)
I figured out - partially how to solve the circular reference problem.
I just iterated over my queried collection (with Include() ) and set the backreferences to the parent to NULL. That worked for the serialisation issue which otherwise already breaks on the server.
The only problem now is the update of a data entity - its failing because the arrays of the referenced entitycollection are static...
To solve the cyclic backreference, you can use the IgnoreDataMember attribute. Or you can set the back reference to NULL before returning the data from the DbDataController
I posted a working solution to your problem in a different question, but using Entity Framework Code First.
https://stackoverflow.com/a/10010695/1226140
Here I show how to generate your client-side model manually, allowing to you to map the data however you please

Model Binding using different names in html markup and models

In an asp.net MVC 1.0 application I have the following action
public ActionResult Submit(ContactModel model)
{
ContentResult ret = new ContentResult();
//do something
return ret;
}
Where ContactModel is defined as:
public class ContactModel
{
public string Name { get; set; }
public string Email { get; set; }
public string Subject { get; set; }
public string Message { get; set; }
public bool Authorization { get; set; }
}
Given that, in the Html Form that posts to this action, the names of the input tags are different from the names of the properties in the class ContactModel. Is there a way to map the html names to the class name so that the model binder can do its job?
The Bind Prefix (see How to use Bind Prefix?),
can partially solve this problem although doesn't allow the definition of full aliases for each property.
The Bind prefix has a strange behaviour though, because it assumes that between the prefix and the name there is a '.' (dot).
I don't think so.
You could create your own modelbinder though. See here for an example

Resources