I'm creating an xml feed of products which needs to match the clients scheme exactly.
I'm using web api. I would like the property extractDate to be an attribute. The following code is outputting extractDate as an element not an attribute
public Feed GetProducts()
{
var feed = new Feed()
{
extractDate = "extractDate",
incremental = true,
name = "name",
Brands = GetBrands(),
Categories = GetCategories(),
Products = GetProducts()
};
return feed;
}
Here is my model Feed. Note the following doesn't seem to turn the element into an attribute
[XmlAttribute(AttributeName = "extractDate")]
public class Feed
{
[XmlAttribute(AttributeName = "extractDate")] //attribute is ignored
public string extractDate { get; set; }
public bool incremental { get; set; }
public string name { get; set; }
public List<Brand> Brands { get; set; }
public List<Category> Categories { get; set; }
public List<Product> Products { get; set; }
}
How do i output
<feed extractDate="2012/01/01"
// other logic
/>
Web API by default uses DataContractSerializer in XmlMediaTypeFormatter and probably that's the reason you are not seeing your attribute decorations taking effect. Do you have the XmlSerializer enabled on the XmlMediaTypeFormatter to see your expected output?
config.Formatters.XmlFormatter.UseXmlSerializer = true;
Also, you could set XmlSerializer only for specific types too using the following api:
config.Formatters.XmlFormatter.SetSerializer<>
Edit
Managed to simulate your issue with a blank project and Kiran's answer seems to do the trick.Just add this line in your controller(for testing purposes, it should probably be in your global.asax)
GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
Do you have the [XmlRoot] on top of your class or is it missing?
Not sure the attribute will work without an xml class decorator.
A simple sanity check you could do is serialize the class without web api involved to make sure it's nothing silly but actually web api related.
How about this:
[XmlRoot("feed")]
public class Feed
{
[XmlAttribute(AttributeName = "extractDate")]
public string extractDate { get; set; }
public bool incremental { get; set; }
public string name { get; set; }
public List<Brand> Brands { get; set; }
public List<Category> Categories { get; set; }
public List<Product> Products { get; set; }
}
Related
I'm developing bulletin board system (as part of my training of asp.net mvc). I have a basic understanding of data modeling, but I have a doubt the way I've created my model. The core logic is to post ad with the following categories realty, auto and service. Initially I tried to use TPH approach, but then faced with problem of binding my models and automapper configuration. Now I think to use zero or one relationship.
I have a Ad model:
public class Ad
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public virtual Realty Realty { get; set; }
public virtual Auto Auto { get; set; }
public virtual Service Service { get; set; }
}
Realty:
public class Realty
{
[Key]
[ForeignKey("Ad")]
public int AdID { get; set; }
public string Type { get; set; }
public string NumberOfRooms { get; set; }
public virtual Ad Ad { get; set; }
}
Auto and service models have the same foreign key as the Realty model.
My db context:
public DbSet<Ad> Ads { get; set; }
public DbSet<Realty> Realties { get; set; }
public DbSet<Auto> Autos { get; set; }
public DbSet<Service> Services { get; set; }
I need update Ad model with one related model only. I'm using scaffolded controller action, which includes all related models:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Title,Descirpiton,Realty,Auto,Service")] Ad ad)
{
if (ModelState.IsValid)
{
db.Ads.Add(ad);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
ViewBag.ID = new SelectList(db.Autos, "AdID", "CarType", ad.ID);
ViewBag.ID = new SelectList(db.Realties, "AdID", "Type", ad.ID);
ViewBag.ID = new SelectList(db.Services, "AdID", "ServiceType", ad.ID);
return View(ad);
}
The problem, that it makes possible to post Ad with all related models together. Before diving deep I wanted to ensure that I'm on a right way of doing this.
Thanks.
You're close. Based on what it looks like you're trying to do you should be using a table-per-type model. You create the base (Ad) and then inherit from it to create the sub-types.
public class Ad
{
[Key]
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
}
[Table("Realty")]
public class Realty : Ad
{
public string Type { get; set; }
public string NumberOfRooms { get; set; }
}
Your context remains the same. You can now create the appropriate sub-type when you know what kind of ad is being created.
var ad = new Realty();
ad.Title = "...";
ad.Description = "...";
ad.Type = "...";
ad.NumberOfRooms = "...";
You can retrieve specific ad types by using the specific type on the context.
db.Realty.ToList();
Or you can retrieve all the ads and interrogate the types as you loop over them.
var ads = db.Ads.ToList();
foreach(var ad in ads)
{
if(ad is Realty)
// do Realty stuff
else if (ad is Auto)
// do Auto stuff
}
I am struggling to get an Item by ID using the asynchronous API of SQLite.Net Async PCL. Here is my model class
public class Invoice : IEntityBase
{
public Invoice()
{
LineItems = new List<LineItem>();
DateCreated = DateTime.Now;
}
[PrimaryKey, AutoIncrement, Column("_id")]
public int Id { get; set; }
public DateTime DateCreated { get; set; }
public int Term { get; set; }
public bool Paid { get; set; }
public decimal Total { get; set; }
public string Notes { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<LineItem> LineItems { get; set; }
}
And the LineItems that has a One to Many relationship here
[PrimaryKey, AutoIncrement, Column("_id")]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
public int Qty { get; set; }
[ForeignKey(typeof(Invoice))]
public int InvoiceId { get; set; }
[ManyToOne]
public Invoice Invoice { get; set; }
Here is the constructor:
public SQLiteAsyncConnection DbConnection;
public InvoiceDatabase(ISQLitePlatform platform, string databasePath)
{
if (DbConnection == null)
{
var connectionAsync = new Func<SQLiteConnectionWithLock>(() =>
new SQLiteConnectionWithLock
(
platform,
new SQLiteConnectionString(databasePath, false)
)
);
DbConnection = new SQLiteAsyncConnection(connectionAsync);
DbConnection.CreateTableAsync<Invoice>();
DbConnection.CreateTableAsync<LineItem>();
}
}
Other CRUD methods (Insert, GetALL) is working except getting an Invoice by ID, and both Visual Studio and Xamarin Studio are not giving me any useful stacktrace.
Here is the Get Method
private readonly InvoiceDatabase _database;
public InvoiceRepository(ISQLitePlatform platform, string databasePath)
{
if (_database == null)
{
_database = new InvoiceDatabase(platform, databasePath);
}
}
public async Task<Invoice> GetInvoice(int id)
{
var result = await _database.DbConnection.Table<Invoice>()
.Where(t => t.Id == id)
.FirstOrDefaultAsync();
return result;
}
I am passing in the Android implementation of SQLite, and like I said the Database is created but I am unable to get the Invoice object back, I even tried
public Task<Invoice> GetInvoiceWithChildren(int id)
{
return _database.DbConnection.GetWithChildrenAsync<Invoice>(id);
}
Any Help will be greatly appreciated.
After three days of chasing shadows it turned out that it is just a very simple thing that is tripping me up. I am tying to save a List of objects like so
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<LineItem> LineItems { get; set; }
I missed the part of the documentation that repeats the fact that SQLite.Net is a lightweight ORM - that point could not be stressed enough so you will have to remove your full size ORM hats such EF. So after reading from the SQLite-Net Extension documentation which says
Text blobbed properties
Text-blobbed properties are serialized into a text property when saved and deserialized when loaded. This allows storing simple objects in the same table in a single column.
Text-blobbed properties have a small overhead of serializing and deserializing the objects and some limitations, but are the best way to store simple objects like List or Dictionary of basic types or simple relationships.
I change my proptery like so and everything is now working as expected. Off now to dealing with the nuances of Async and Await
[TextBlob("LineItemBlobbed")]
public List<LineItem> LineItems { get; set; }
public string LineItemBlobbed { get; set; }
I am attempting to add a row to a Class in my Parse database using the API
I have managed to get the row added but I noticed that both the 'ACL & user__user' fields are blank.
My Request class looks like this:
public class AccountDataRequest
{
public string OrderNo { get; set; }
public string SiteName { get; set; }
public string CreditDebit { get; set; }
public int Amount { get; set; }
public int CreditBalance { get; set; }
}
And my function looks like this:
public static AccountDataResponse AddTransaction(AccountDataRequest details)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.parse.com/1/classes/AccountData");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.Headers.Add("X-Parse-Application-Id", "xxxxx");
httpWebRequest.Headers.Add("X-Parse-REST-API-Key", "xxxxx");
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = JsonConvert.SerializeObject(details);
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return JsonConvert.DeserializeObject<AccountDataResponse>(result);
}
}
}
The 'user__user' links to the 'objectID(String)' in mu Users class.
I have tried adding it to my class as a string but it throws and error.
Can anyone tell me how to get the ACL and 'user__user' populated please?
Thanks
UPDATE:
I have learnt that the Pointer is a structure so have amended my classes as follows:
public class AccountDataRequest
{
public string OrderNo { get; set; }
public string SiteName { get; set; }
public string CreditDebit { get; set; }
public double Amount { get; set; }
public int CreditBalance { get; set; }
public Pointer Pointer { get; set; }
}
public class Pointer
{
public string __type { get; set; }
public string className { get; set; }
public string objectId { get; set; }
}
So, when I now call the API with the following:
POST https://api.parse.com/1/classes/AccountData HTTP/1.1
Content-Type: application/json
X-Parse-Application-Id: xxxxx
X-Parse-REST-API-Key: xxxxx
Host: api.parse.com
Content-Length: 163
Expect: 100-continue
Connection: Keep-Alive
{"OrderNo":"9","SiteName":"Trev","CreditDebit":"Debit","Amount":1.0,"CreditBalance":999,"Pointer":{"__type":"Pointer","className":"AccountData","objectId":"fvJ8jPjyjx"}}
This call produces no errors and returns a createddate and an objectid but the user(Pointer <__User> is still null.
I also tried changing the className to "__User" to which the API responds:
{"code":111,"error":"invalid type for key Pointer, expected *AccountData, but got *_User"}
This is what the empty column looks like in my AccountData class
And I am trying to tie it to the objectId in my User table:
Can anyone see what is wrong please?
If the column in Parse is defined as a Pointer to _User, then you need to pass the appropriate structure to Parse and not just the objectId. Take a look at the Data Types section of the Parse REST SDK. It has a paragraph and sample for passing a Pointer structure through the API.
Similarly, for ACLs you need to specify that structure as well. Details for it are in the security docs for the SDK.
In both cases, if you want to use an object->JSON converter, you'll need to build an object that appropriately represents that structure. That'll be a bit easier for Pointers than ACLs as the former has predefined keys whereas the latter uses dynamic key names (e.g. objectIds and role names).
Updated to include class definition
public class AccountDataRequest
{
public string OrderNo { get; set; }
public string SiteName { get; set; }
public string CreditDebit { get; set; }
public double Amount { get; set; }
public int CreditBalance { get; set; }
public Pointer user { get; set; }
}
I'm having trouble passing view information from my Get/Create action to my view. Here are my three model classes;
public class Competition
{
public int Id { get; set; }
public int CompetitionId { get; set; }
public string Name { get; set; }
public string Prize { get; set; }
}
public class CompetitionEntry
{
public int Id { get; set; }
public int CompetitionEntryId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int CompetitionId { get; set; }
}
public class CompetitionEntryViewModel
{
public int Id { get; set; }
public Competition Competitions { get; set; }
public int CompetitionId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
Here is my Get/Create action in CompetitionEntry Controller;
public ActionResult Create(int id)
{
CompetitionEntryViewModel competitionentryviewmodel = db.CompetitionEntriesView.Find(id);
return View(competitionentryviewmodel);
}
I know this doesn't work. The id parameter goes into the URL fine. How to I get access to my Competition class in th Get action? I need to be able to show the competion name on my Create Competition entry view.
Thanks in advance!
public ActionResult Create(int id)
{
var data = db.CompetitionEntriesView.Find(id);
CompetitionEntryViewModel competitionentryviewmodel = new CompetitionEntryViewModel();
competitionentryviewmodel.CompetitionName = data.Name;
return View(competitionentryviewmodel);
}
What you are trying to do is build an object graph and display it through a view model. In order to do this, you need to map your domain model(s) to your view model.
You can do the mapping yourself by writing a lot of code (re-inventing the wheel), or, you could consider using third party tools to do this for you. I recommend you use an AutoMapper as it is very simple to use imo.
The other problem is that your view model contains a domain model. This is likely to cause you a lot of headache in near future. If I were you, I would replace Competition with CompetitionViewModel.
I would also consider creating a view model for a list of competitions, i.e. CompetitionsViewModel. Look into partial views to see how you can display a list of competitions.
Good luck
I have a Solution under the solution there is few Projects one of the called DomainModel,
in which i write my models and other stuff mainly infrastructure.
Now i have another project called WebUI in which i do my UI (Views, Controllers , etc...)
I want to use Remote attribute in DomainModel project which must implemented in WebUI certain view.
When i use it in DomainModel it's gives me an error, that it does not recognize the Controller and it's correct it does not recognize it because the if I add the reference of WebUI the Vs begin to swear at me because it will be a circular reference.
How to implement this?
this is my code
Controller that serves the RemoteValidation
[OutputCache(Location = OutputCacheLocation.None, NoStore = true)]
public class RemoteValidationController : Controller
{
public JsonResult CheckPassword(string SmsCode)
{
return Json(12345, JsonRequestBehavior.AllowGet);
}
}
//The real entity in DomainModel project
public class SmsCustomer
{
public int CustomerId { get; set; }
public string Cli { get; set; }
//this is what i have to validate on server
public virtual string SmsCode { get; set; }
public DateTime InsertDate { get; set; }
public int CustomerDaysChoiceId { get; set; }
public int CustomerAmountChoiceId { get; set; }
[Required(ErrorMessage = "error")]
[StringLength(128, ErrorMessage = "error")]
public string SelectedWords { get; set; }
public SmsCustomerDaysChoice CustomerDaysChoice { get; set; }
public SmsCustomerAmountChoice CustomerAmountChoice { get; set; }
}
this is my entity after i extend it with the remote attr in WebUI.Models
public class Customer : SmsCustomer
{
[Required(ErrorMessage = "Error required")]
[StringLength(9, ErrorMessage = "Error length")]
[Remote("CheckPassword", "RemoteValidation", ErrorMessage = "Error remote")]
public override string SmsCode { get; set; }
}
this is my view
#Html.TextBoxFor(c => c.SmsCode)
//error span
<span class="checkbox-form-error" data-valmsg-for="SmsCode" data-valmsg-replace="true"> </span>
The remote validation stuff is very specific to the WebUI project.
Because of this, I'd create a View model that inherits from the actual class, and then override the property that needs remote validation. Then you should be able to specify the controller/action for remote validation.
You can also put your validation in a class of its own, like ScottGu demonstrates here:
http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx
(Look down the post, before the last step)
Also take a look at this: Adding DataAnnontations to Generated Partial Classes