How to avoid to pass null entity object to web api method - asp.net-web-api

I have below web api method as below
public bool UpdateValidations([FromBody] ValidationKeyEntity validationKey)
{
if (ModelState.IsValid)
{
//my code here
}
}
public class ValidationKeyEntity
{
public int ValidationKeyId { get; set; }
[MaxLength(Constants.maxStringLength)]
public string Name { get; set; }
public int DisplayId { get; set; }
[MaxLength(Constants.maxStringLength)]
public string CreatedBy { get; set; }
}
I am doing testing using Postman .I am passing different json than ValidationKeyEntity object as { "Vishal": "vishal" } as parameter .
But still my ModelState.IsValid returns true.
How can I avoid accepting other json object than "ValidationKeyEntity" object?

Use RequiredAttribute to mark the properties as required:
public class ValidationKeyEntity
{
[Required]
public int ValidationKeyId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int DisplayId { get; set; }
[Required]
public string CreatedBy { get; set; }
}
Set MissingMemberHandling globally to handle waste properties:
var httpConfiguration = new HttpConfiguration();
httpConfiguration
.Formatters
.JsonFormatter
.SerializerSettings
.MissingMemberHandling = MissingMemberHandling.Error;

Related

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type because the type requires a JSON array

My api get json data like this
Office "دكتور نيوترشن"
officename "11111111"
address_user "سيتي مول"
profile_photo "profile_photo.png"
cover_photo "cover_photo.jpg"
agentarea "القطيف"
offertext "قريبا سوف توضح المصومات"
websiteurl "albatool-hdo"
and in xamarin android I am creating this class
public class Galeri
{
public Galeri()
{
}
public string Office { get; set; }
public string officename { get; set; }
public string address_user { get; set; }
public string profile_photo { get; set; }
public string cover_photo { get; set; }
public string agentarea { get; set; }
public string offertext { get; set; }
public string websiteurl { get; set; }
public string membertype { get; set; }
}
and also I am using this code to deserialized json
RunOnUiThread(() =>
{
itemGaleri = JsonConvert.DeserializeObject<List<Galeri>>(e.Result);
CustomListAdapter adapter = new CustomListAdapter(this, itemGaleri);
DaftarGaleri.Adapter = adapter;
progress.Visibility = ViewStates.Gone;
DaftarGaleri.ItemClick += DaftarGaleri_ItemClick;
}
);
but Iam getting an error
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type '' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
Next time when you have to deal with JSON and you want to quickly generate the C# models use services like https://app.quicktype.io. Now just give a logical names to your properties like Galeri instead of Welcome.
// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do:
//
// using QuickType;
//
// var data = Welcome.FromJson(jsonString);
namespace QuickType
{
using System;
using System.Net;
using System.Collections.Generic;
using Newtonsoft.Json;
public partial class Welcome
{
[JsonProperty("Office")]
public string Office { get; set; }
[JsonProperty("officename")]
public string Officename { get; set; }
[JsonProperty("address_user")]
public string AddressUser { get; set; }
[JsonProperty("profile_photo")]
public string ProfilePhoto { get; set; }
[JsonProperty("cover_photo")]
public string CoverPhoto { get; set; }
[JsonProperty("agentarea")]
public string Agentarea { get; set; }
[JsonProperty("offertext")]
public string Offertext { get; set; }
[JsonProperty("websiteurl")]
public string Websiteurl { get; set; }
[JsonProperty("membertype")]
public string Membertype { get; set; }
}
public partial class Welcome
{
public static Welcome[] FromJson(string json) => JsonConvert.DeserializeObject<Welcome[]>(json, Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this Welcome[] self) => JsonConvert.SerializeObject(self, Converter.Settings);
}
public class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
};
}
}

ServiceStack validators not firing

I am trying to use fluent validation in ServiceStack. I've added the validation plugin and registered my validator.
Plugins.Add(new ValidationFeature());
container.RegisterValidators(typeof(CreateLeaveValidator).Assembly);
I have implemented a validator class for my service model:
public class CreateLeaveValidator : AbstractValidator<CreateLeave>
{
public CreateLeaveValidator()
{
RuleFor(cl => cl.StudentId).NotEmpty();
RuleFor(cl => cl.LeaveDepart).NotEmpty().GreaterThan(DateTime.Now).WithMessage("Leave must begin AFTER current time and date.");
RuleFor(cl => cl.LeaveReturn).NotEmpty().GreaterThan(cl => cl.LeaveDepart).WithMessage("Leave must end AFTER it begins.");
RuleFor(cl => cl.ApprovalStatus).Must( status => ( ("P".Equals(status)) || ("C".Equals(status)) || ("A".Equals(status)) || ("D".Equals(status)) ) );
}
}
Service Model:
[Route("/leaves", "POST")]
public class CreateLeave : IReturn<LeaveResponse>, IUpdateApprovalStatus
{
public int StudentId { get; set; }
public DateTime RequestDate { get; set; }
public DateTime LeaveDepart { get; set; }
public DateTime LeaveReturn { get; set; }
public string Destination { get; set; }
public string HostRelationship { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Postal { get; set; }
public string Hostphone { get; set; }
public string Cellphone { get; set; }
public string Transport { get; set; }
public string Driver { get; set; }
public string Companions { get; set; }
public string Reason { get; set; }
public string ApprovalStatus { get; set; }
public DateTime ApprovalDate { get; set; }
public string ApprovalComment { get; set; }
public string ApprovalReason { get; set; }
public int ApprovalUser { get; set; }
}
But when I create a request with no StudentId or an invalid ApprovalStatus, the validator does not appear to fire and catch the invalid request.
How can I go about troubleshooting the cause of this?
UPDATE: Correction it appears validators are working with my actual service but not in my unit tests. I'm guessing I must not be configuring my apphost correctly in the unit test setup. Here's my test constructor:
public LeaveTests()
{
Licensing.RegisterLicense(#"[license key]");
appHost = new BasicAppHost(typeof(ApiServices).Assembly).Init();
ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601;
appHost.Plugins.Add(new ValidationFeature());
appHost.Container.RegisterValidators(typeof(CreateLeaveValidator).Assembly);
}
ServiceStack Validation filters are executed in a Global Request Filter which require a full integration test to run, e.g:
public class MyIntegrationTests
{
ServiceStackHost appHost;
public MyIntegrationTests()
{
appHost = new AppHost()
.Init()
.Start("http://localhost:8000/");
}
[OneTimeTearDown] void OneTimeTearDown() => appHost.Dispose();
[Test]
public void Execute_validation_filters()
{
var client = new JsonServiceClient("http://localhost:8000/");
try
{
var response = client.Post(new CreateLeave { ... });
}
catch(WebServiceException ex)
{
//...
}
}
}

Microsoft Cognitive Services Web Search API - DeSerialization Issues

I want to learn Cognitive Services Web Search APIs so I started creating a bot application . I already have a account sub- key and other required information also I read many articles and watch build 2016 videos on this as well.I am having trouble while deserializing the result .
I am not able to find the proxy class that I can use to do that .
The url I am using is https://api.cognitive.microsoft.com/bing/v5.0/search/
and I found a proxy class for previous api version . Can anybody tell me how to get proxy class of the api request / response in VS 2015 for these service.
My Code look like this:
string BingSearchUrl = "https://api.cognitive.microsoft.com/bing/v5.0/search/";
const string bingKey = "Key";
public static async Task<string> Search(string query)
{
var client = HttpClientFactory.Create();
var queryString = BingSearchUrl + "?q=" + query + "&count=10";
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", bingKey);
client.DefaultRequestHeaders.Add("Accept", "application/json");
// Request parameters
string r = await client.GetStringAsync(queryString);
var jsonResult = JsonConvert.DeserializeObject<Bing.ExpandableSearchResult>(r);
return jsonResult.Web.First().Title;
Try below code
public string BingSearchUrl = "https://api.cognitive.microsoft.com/bing/v5.0/search/";
const string bingKey =[KEY];
public async void Search()
{
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", bingKey);
// Request parameters
queryString["q"] = "microsoft";
queryString["count"] = "10";
queryString["offset"] = "0";
queryString["mkt"] = "en-us";
queryString["safeSearch"] = "Moderate";
var uri = "https://api.cognitive.microsoft.com/bing/v5.0/news/search?" + queryString;
var response = await client.GetStringAsync(uri);
var jsonResult = JsonConvert.DeserializeObject<BingJson>(response);
string title = jsonResult.value[0].name.ToString();
}
With the jsonResult.value[0] you can loop through the results. First results is at [0] position.
I Created a model class looking at the bing search response json. It looks like,
public class BingJson
{
public string _type { get; set; }
public Instrumentation instrumentation { get; set; }
public string readLink { get; set; }
public int totalEstimatedMatches { get; set; }
public Value[] value { get; set; }
}
public class Instrumentation
{
public string pingUrlBase { get; set; }
public string pageLoadPingUrl { get; set; }
}
public class Value
{
public string name { get; set; }
public string url { get; set; }
public string urlPingSuffix { get; set; }
public Image image { get; set; }
public string description { get; set; }
public About[] about { get; set; }
public Provider[] provider { get; set; }
public DateTime datePublished { get; set; }
public string category { get; set; }
}
public class Image
{
public Thumbnail thumbnail { get; set; }
}
public class Thumbnail
{
public string contentUrl { get; set; }
public int width { get; set; }
public int height { get; set; }
}
public class About
{
public string readLink { get; set; }
public string name { get; set; }
}
public class Provider
{
public string _type { get; set; }
public string name { get; set; }
}
With this model, I am able to get the desired result. The Model which is presented in the other answer is not working in my case.
namespace BingSearchBot
{
public class RootObject
{
public string _type { get; set; }
public WebPages webPages { get; set; }
public RelatedSearches relatedSearches { get; set; }
public RankingResponse rankingResponse { get; set; }
}
public class WebPages
{
public string webSearchUrl { get; set; }
public int totalEstimatedMatches { get; set; }
public List<Value> value { get; set; }
}
public class Value
{
public string id { get; set; }
public string name { get; set; }
public string url { get; set; }
public List<About> about { get; set; }
public string displayUrl { get; set; }
public string snippet { get; set; }
public List<DeepLink> deepLinks { get; set; }
public string dateLastCrawled { get; set; }
public List<SearchTag> searchTags { get; set; }
}
public class About
{
public string name { get; set; }
}
public class DeepLink
{
public string name { get; set; }
public string url { get; set; }
public string snippet { get; set; }
}
public class SearchTag
{
public string name { get; set; }
public string content { get; set; }
}
public class Value2
{
public string text { get; set; }
public string displayText { get; set; }
public string webSearchUrl { get; set; }
}
public class RelatedSearches
{
public string id { get; set; }
public List<Value2> value { get; set; }
}
public class Value3
{
public string id { get; set; }
}
public class Item
{
public string answerType { get; set; }
public int resultIndex { get; set; }
public Value3 value { get; set; }
}
public class Mainline
{
public List<Item> items { get; set; }
}
public class RankingResponse
{
public Mainline mainline { get; set; }
}
}

JSON serialization fails with parent/child related entities in EF 6.1

I see that other folks have add issue with this error when trying to serialize an entity that has a navigation property to a collection of other entities such as in a parent child relationship.
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.",
I have tried added these options to the Register method inside the WebApiConfig.cs file but I still get the same error.
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
Best way I found to do this is to add
[JsonIgnore]
attributes in the entity for the references that you don't need to serialize (I use buddy classes to annotate the entities). This is an example:
[MetadataType(typeof(MenuItemValidation))]
public partial class MenuItem
{
public class MenuItemValidation
{
public int Id { get; set; }
public int Menu_Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Url { get; set; }
[Required]
public int SortOrder { get; set; }
public bool HasIcon { get; set; }
public string IconClass { get; set; }
public bool IsActive { get; set; }
public bool IsDeleted { get; set; }
[JsonIgnore]
public System.DateTime CreatedOn { get; set; }
[JsonIgnore]
public System.Guid CreatedBy_Id { get; set; }
[JsonIgnore]
public System.DateTime UpdatedOn { get; set; }
[JsonIgnore]
public System.Guid UpdatedBy_Id { get; set; }
public bool IsMegaMenu { get; set; }
public virtual ICollection<MenuItem> Children { get; set; }
[JsonIgnore]
public virtual MenuItem Parent { get; set; }
[JsonIgnore]
public virtual Menu Menu { get; set; }
[JsonIgnore]
public virtual User CreatedBy { get; set; }
[JsonIgnore]
public virtual User UpdatedBy { get; set; }
[JsonIgnore]
public virtual ICollection<MenuItemsLocalization> MenuItemsLocalizations { get; set; }
}
}
I also added:
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
inside App_Start/WebApiConfig.cs

RestSharp - WP7 - Cannot deserialize XML to a list

I use RestSharp in my Windows Phone 7.1 project.
I have a response in XML format here:
https://skydrive.live.com/redir.aspx?cid=0b39f4fbbb0489dd&resid=B39F4FBBB0489DD!139&parid=B39F4FBBB0489DD!103&authkey=!AOdT-FiS6Mw8v5Y
I tried to deserialize that response to a class:
public class fullWall
{
public _user user { get; set; }
public int numberOfFriend { get; set; }
public int numberOfPhoto { get; set; }
public List<timhotPhotos> timhotPhotos { get; set; }
public fullWall()
{
timhotPhotos = new List<timhotPhotos>();
}
}
All properties are ok except the timhotPhotos list, as you can see here:
timhotPhotos class:
public class timhotPhotos
{
public string id { get; set; }
public string title { get; set; }
public string description { get; set; }
public string url { get; set; }
public double width { get; set; }
public double height { get; set; }
public DateTime createdDate { get; set; }
public _user user { get; set; }
public int numOfComment { get; set; }
public int numOfRate { get; set; }
public int numOfView { get; set; }
public bool rated { get; set; }
}
Where am I wrong?
You'll have to change the default XML deserializer to the DotNetXmlDeserializer, like this:
RestClient client;
client.AddHandler("application/xml", new DotNetXmlDeserializer());
Then, add the XmlElement attribute to the List<timhotPhotos> timhotPhotos property like this:
public class fullWall
{
public _user user { get; set; }
public int numberOfFriend { get; set; }
public int numberOfPhoto { get; set; }
[System.Xml.Serialization.XmlElement()]
public List<timhotPhotos> timhotPhotos { get; set; }
public fullWall()
{
timhotPhotos = new List<timhotPhotos>();
}
}
Now it should work fine!

Resources