ServiceStack .NET Silverlight wrong result - servicestack

I'm tring to set up a sample demo running ServiceStack with Silverlight. I've read this article
and I've successfully been able to invoke the method on server...
Currently my demo app is made of
Name.Web (Service and Silverlight hoster)
Name.Web.DTO contains request/response classes
Name.Silverlight (main SL application)
Name.Silverlight.DTO contains a copy (Add as Link in VS) of the class
in Name.Web.DTO
My sevice class is
public class TestService : Service
{
public object Any (TestRequest request)
{
var lst = new List<TestResponse>();
for (int i = 0; i < 20; i++)
{
var item = new TestResponse { ID = i, Descrizione = string.Format("Descr_{0}", i) };
lst.Add(item);
}
return lst;
}
}
And the response/request are really simple
[Route("/test")]
public class TestRequest : IReturn<IList<TestResponse>>
{
}
[DataContract]
public class TestResponse
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Descrizione { get; set; }
}
On silverlight part in the serviceClient_Completed I've 20 items (as service produce) but all with ID=0,Descrizione=string.Empty
What can be the reason of this? I've also tried looking with FireBug/Fiddler but I don't see anything (maybe since I'm on localhost?) or that's due to the fact serviceClient is made via ClientHttp?
var webRequest = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(_baseUri + uri));
Thanks in advance

Related

Error when adding Where or OrderBy clauses to Azure Mobile Apps request

I'm developing an Azure Mobile App service to interface to my Xamarin application.
I've created, connected and successfully populated an SQL Database, but when I try to add some filters to my request, for example an orderby() or where() clauses, it returns me a Bad Request error.
For example, this request: https://myapp.azurewebsites.net/tables/Race?$orderby=iRound%20desc,iYear%20desc&$top=1&ZUMO-API-VERSION=2.0.0 gives me {"message":"The query specified in the URI is not valid. Could not find a property named 'IYear' on type 'MyType'."}.
My configuration method is this:
HttpConfiguration config = new HttpConfiguration();
new MobileAppConfiguration()
.AddTablesWithEntityFramework()
.ApplyTo(config);
config.MapHttpAttributeRoutes();
Database.SetInitializer(new CreateDatabaseIfNotExists<MainDataContext>());
app.UseWebApi(config);
and my DbContext is this:
public class MainDataContext : DbContext
{
private const string connectionStringName = "Name=MS_TableConnectionString";
public MainDataContext() : base(connectionStringName)
{
Database.Log = s => WriteLog(s);
}
public void WriteLog(string msg)
{
System.Diagnostics.Debug.WriteLine(msg);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(
new AttributeToColumnAnnotationConvention<TableColumnAttribute, string>(
"ServiceTableColumn", (property, attributes) => attributes.Single().ColumnType.ToString()));
}
public DbSet<Race> Race { get; set; }
public DbSet ...ecc...
}
Following this guide, I added a migration after creating my TableControllers. So the TableController for the example type shown above is pretty standard:
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public class RaceController : TableController<Race>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
MainDataContext context = new MainDataContext();
DomainManager = new EntityDomainManager<Race>(context, Request);
}
// GET tables/Race
[EnableQuery(AllowedQueryOptions = AllowedQueryOptions.All)]
public IQueryable<Race> GetAllRace()
{
return Query();
}
// GET tables/Race/48D68C86-6EA6-4C25-AA33-223FC9A27959
public SingleResult<Race> GetRace(string id)
{
return Lookup(id);
}
// PATCH tables/Race/48D68C86-6EA6-4C25-AA33-223FC9A27959
public Task<Race> PatchRace(string id, Delta<Race> patch)
{
return UpdateAsync(id, patch);
}
// POST tables/Race
public async Task<IHttpActionResult> PostRace(Race item)
{
Race current = await InsertAsync(item);
return CreatedAtRoute("Tables", new { id = current.Id }, current);
}
// DELETE tables/Race/48D68C86-6EA6-4C25-AA33-223FC9A27959
public Task DeleteRace(string id)
{
return DeleteAsync(id);
}
}
As you can see, I already tried to add the EnableQuery attribute to my TableController, as seen on Google. I also tried to add these filters to the HttpConfiguration object, without any success:
config.Filters.Add(new EnableQueryAttribute
{
PageSize = 10,
AllowedArithmeticOperators = AllowedArithmeticOperators.All,
AllowedFunctions = AllowedFunctions.All,
AllowedLogicalOperators = AllowedLogicalOperators.All,
AllowedQueryOptions = AllowedQueryOptions.All
});
config.AddODataQueryFilter(new EnableQueryAttribute
{
PageSize = 10,
AllowedArithmeticOperators = AllowedArithmeticOperators.All,
AllowedFunctions = AllowedFunctions.All,
AllowedLogicalOperators = AllowedLogicalOperators.All,
AllowedQueryOptions = AllowedQueryOptions.All
});
I don't know what to investigate more, as things seems to be changing too fast for a newbie like me who's first got into Azure.
EDIT
I forgot to say that asking for the complete table, so for example https://myapp.azurewebsites.net/tables/Race?ZUMO-API-VERSION=2.0.0, returns correctly the entire dataset. The problem occurs only when adding some clauses to the request.
EDIT 2
My model is like this:
public class Race : EntityData
{
public int iRaceId { get; set; }
public int iYear { get; set; }
public int iRound { get; set; }
ecc..
}
and the database table that was automatically created is this, including all the properties inherited from EntityData:
Database table schema
Digging into the source code, Azure Mobile Apps sets up camelCase encoding of all requests and responses. It then puts them back after transmission accordign to rules - so iRaceId becomes IRaceId on the server.
The easiest solution to this is to bypass the auto-naming and use a JsonProperty attribute on each property within your server-side DTO and client-side DTO so that they match and will get encoding/decoded according to your rules.
So:
public class Race : EntityData
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("raceId")]
public int iRaceId { get; set; }
[JsonProperty("year")]
public int iYear { get; set; }
[JsonProperty("round")]
public int iRound { get; set; }
etc..
}

How to get nested element using ServiceStack?

Although I am able to access the SchemaVersion using code below, I cannot access FormatDocID nested element.
Any ideas how can I easily get FormatDocID using ServiceStack and AutoQueryFeature (or similar)?
I put only relevant parts of code here
public override void Configure(Container container)
{
JsConfig.DateHandler = DateHandler.ISO8601;
SetupValidators(container);
SetupIOC(container);
SetupPlugins(container, log);
ContentTypes.Register("application/xml"
, CLXmlSerializer.Serialize, ServiceStack.Text.XmlSerializer.DeserializeFromStream);
SetupMetaDataRedirectionPath();
SetupGlobalResponseFilters();
}
Setup plugins
private void SetupPlugins(Container container)
{
Plugins.Add(new ValidationFeature());
Plugins.Add(new SwaggerFeature());
Plugins.Add(new AutoQueryFeature
{
MaxLimit = 1000,
EnableUntypedQueries = false,
IncludeTotal = true
});
Plugins.Add(new AutoQueryDataFeature {MaxLimit = 100}
.AddDataSource(ctx => ctx.MemorySource(new List<WordDocument>
{
new WordDocument()
{
SchemaVersion = "",
Format = new Word.DocumentFormat()
{
FormatDocID = 254
}
}
}))
);
typeof(RequestLogs).AddAttributes(new RestrictAttribute {VisibilityTo = RequestAttributes.None});
typeof(AssignRoles).AddAttributes(new RestrictAttribute {VisibilityTo = RequestAttributes.None});
typeof(UnAssignRoles).AddAttributes(new RestrictAttribute {VisibilityTo = RequestAttributes.None});
typeof(Authenticate).AddAttributes(new RestrictAttribute {VisibilityTo = RequestAttributes.None});
}
Serializable classes
public abstract class Document
{
public DocumentFormat Format;
public class DocumentFormat
{
[XmlAttribute] public int Version;
public int FormatDocID;
public string DocShortName;
}
}
public class WordDocument : Document
{
[XmlAttribute] public string SchemaVersion { get; set; } = "1.0";
}
Thanks in advance for the answers.
It's not clear what you're trying to achieve or why, AutoQuery creates Auto Queryable APIs where the Response is the API Response serialized in the specified Response Content Type.
If you want to intercept the Typed Response DTO before it's returned you can create a Custom AutoQuery Implementation and introspect the response that way, e.g:
public class MyQueryServices : Service
{
public IAutoQueryData AutoQuery { get; set; }
//Override with custom implementation
public object Any(MyQuery query)
{
var q = AutoQuery.CreateQuery(query, base.Request);
var response = AutoQuery.Execute(query, q);
return response;
}
}
But the AutoQuery Memory Data Source you're using lets you provide your own collection of Typed POCOs as the Data source so you already have access to them when you create it, but the source POCOs should be a flat Type with public properties (in contrast to your class with public fields and nested types) - it's not possible to query nested object graph values.
This is an example of a POCO that doesn't use nested classes, or public fields:
public abstract class Document
{
public int Version { get; set; }
public int FormatDocID { get; set; }
public string DocShortName { get; set; }
}
So the solution if you want to use AutoQuery would be to change your Data Source to use Flat POCOs with public properties otherwise you'd need to create the impl of your Service yourself.

CustomPrincipal.IsInRole in ASP.NET MVC5

I am working in ASP.NET MVC 5 and I am using ASP.NET Identity. I have followed LukeP's solution here to get access to my ApplicationUser custom properties (e.g. User.DisplayUsername or User.DOB). Like Luke has suggested, I now have a custom IPrincipal implementation (basically exact same code as him).
This has a problem however, and I suspect it is do with with this line of code on the CustomPrincipal class:
public bool IsInRole(string role) { return false; }
I have a controller called ReviewController and on there I have this:
[Authorize(Roles = "Admin")]
public class ReviewController : Controller
{
// controller stuff
}
This isn't working. Even though the user I am logged in as is of role Admin. So I tried improving the code by doing this to the IsInRole method:
public class CustomPrincipal : ICustomPrincipal
{
public IIdentity Identity { get; private set; }
public bool IsInRole(string role)
{
var roleManager = new RoleManager<IdentityRole>(new RoleStore<IdentityRole>(new BBContext()));
return roleManager.Roles.All(r => r.Name == role);
}
public CustomPrincipal(string email)
{
this.Identity = new GenericIdentity(email);
}
public string Id { get; set; }
public string DisplayUsername { get; set; }
public DateTime DOB { get; set; }
}
This has improved in the sense that I am now served the ReviewController. However it is still wrong because even user that are not in the Admin role are also allowed access. I know why that is too, but just don't know how to fix this.
How can I get it to work as it should?

Does ServiceStack support generics in end-to-end typed requests

I was playin' around with ServiceStack and was wondering if it supported this scenario. I'm using generics in my request types so that many DTOs that inherit from a common interface will support the same basic methods [ like... GetById(int Id) ].
Using a request type specific to a single kind of DTO works, but breaks the generics nice-ness...
var fetchedPerson = client.Get<PersonDto>(new PersonDtoGetById() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson.Id)); //PASS
Mapping a route to the generic also works:
Routes.Add<DtoGetById<PersonDto>>("/persons/{Id}", ApplyTo.Get);
...
var fetchedPerson2 = client.Get<PersonDto>(string.Format("/persons/{0}", person.Id));
Assert.That(person.Id, Is.EqualTo(fetchedPerson2.Id)); //PASS
But using the end-to-end generic request type fails:
var fetchedPerson3 = client.Get<PersonDto>(new DtoGetById<PersonDto>() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson3.Id)); //FAIL
I wonder if I'm just missing something, or if i'm trying to abstract just ooone layer too far... :)
Below is a complete, failing program using NUnit, default ServiceStack stuff:
namespace ssgenerics
{
using NUnit.Framework;
using ServiceStack.ServiceClient.Web;
using ServiceStack.ServiceHost;
using ServiceStack.ServiceInterface;
using ServiceStack.WebHost.Endpoints;
[TestFixture]
class Program
{
public static PersonDto GetNewTestPersonDto()
{
return new PersonDto()
{
Id = 123,
Name = "Joe Blow",
Occupation = "Software Developer"
};
}
static void Main(string[] args)
{}
[Test]
public void TestPutGet()
{
var listeningOn = "http://*:1337/";
var appHost = new AppHost();
appHost.Init();
appHost.Start(listeningOn);
try
{
var BaseUri = "http://localhost:1337/";
var client = new JsvServiceClient(BaseUri);
var person = GetNewTestPersonDto();
client.Put(person);
var fetchedPerson = client.Get<PersonDto>(new PersonDtoGetById() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson.Id));
var fetchedPerson2 = client.Get<PersonDto>(string.Format("/persons/{0}", person.Id));
Assert.That(person.Id, Is.EqualTo(fetchedPerson2.Id));
Assert.That(person.Name, Is.EqualTo(fetchedPerson2.Name));
Assert.That(person.Occupation, Is.EqualTo(fetchedPerson2.Occupation));
var fetchedPerson3 = client.Get<PersonDto>(new DtoGetById<PersonDto>() { Id = person.Id });
Assert.That(person.Id, Is.EqualTo(fetchedPerson3.Id));
Assert.That(person.Name, Is.EqualTo(fetchedPerson3.Name));
Assert.That(person.Occupation, Is.EqualTo(fetchedPerson3.Occupation));
}
finally
{
appHost.Stop();
}
}
}
public interface IDto : IReturnVoid
{
int Id { get; set; }
}
public class PersonDto : IDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Occupation { get; set; }
}
public class DtoGetById<T> : IReturn<T> where T : IDto { public int Id { get; set; } }
public class PersonDtoGetById : IReturn<PersonDto> { public int Id { get; set; } }
public abstract class DtoService<T> : Service where T : IDto
{
public abstract T Get(DtoGetById<T> Id);
public abstract void Put(T putter);
}
public class PersonService : DtoService<PersonDto>
{
public override PersonDto Get(DtoGetById<PersonDto> Id)
{
//--would retrieve from data persistence layer
return Program.GetNewTestPersonDto();
}
public PersonDto Get(PersonDtoGetById Id)
{
return Program.GetNewTestPersonDto();
}
public override void Put(PersonDto putter)
{
//--would persist to data persistence layer
}
}
public class AppHost : AppHostHttpListenerBase
{
public AppHost()
: base("Test HttpListener",
typeof(PersonService).Assembly
) { }
public override void Configure(Funq.Container container)
{
Routes.Add<DtoGetById<PersonDto>>("/persons/{Id}", ApplyTo.Get);
}
}
}
No, It's a fundamental concept in ServiceStack that each Service requires its own unique Request DTO, see this answer for more examples on this.
You could do:
[Route("/persons/{Id}", "GET")]
public class Persons : DtoGetById<Person> { ... }
But I strongly advise against using inheritance in DTOs. Property declaration is like a DSL for a service contract and its not something that should be hidden.
For more details see this answer on the purpose of DTO's in Services.

Deserializing a json string to C#.net classes using JsonConvert.DeserializeObject (v 4.0.8.14612)

In my web app, I have written some tests to test my deserializing logic that parses a json string in to my C# classes. These tests runs fine on my computer, but they fail on our CI environment with this error message:
Test(s) failed. System.TypeInitializationException : The type initializer for 'Newtonsoft.Json.JsonConvert' threw an exception. ----> System.Security.VerificationException : Operation could destabilize the runtime.
One json string example is this (from the test class):
private const string MatrikkelJson = "{'Gaardsnummer':'9','Bruksnummer':'9','Festenummer':'8','Seksjonsnummer':'8','BlankAllowed':'False','AttrType':'Matrikkel'}";
This string should be deserialized to this class:
public class MatrikkelDTO : AttributeBaseDTO
{
public string Gaardsnummer { get; set; }
public string Bruksnummer { get; set; }
public string Festenummer { get; set; }
public string Seksjonsnummer { get; set; }
}
public class AttributeBaseDTO
{
public bool BlankAllowed { get; set; }
public string AttrType { get; set; }
}
The method that deserializes the json string works like this:
I first deserialize the baseobject to get the AttrType property. Using that information I deserialize the json string to the specific type (I have several classes that inherits from AttributBaseDTO.
public AttributeValidationHandlerResponse ValidateAttribute(string serializedObject)
{
var response = new AttributeValidationHandlerResponse();
response.Result = false;
//hack... this handler gets called when opening newdocument.aspx. don't know why.
if (serializedObject.Contains("function"))
{
response.Message = "";
return response;
}
if (String.IsNullOrEmpty(serializedObject))
{
response.Message = "attributeobject";
return response;
}
var message = "";
var attributeBase = JsonConvert.DeserializeObject<AttributeBaseDTO>(serializedObject);
if (attributeBase.AttrType == "Matrikkel")
{
var attribute = ConvertJsonStringToAttribute<MatrikkelDTO>(serializedObject);
response = ValidateMatrikkel(attribute);
}
return response;
}
internal T ConvertJsonStringToAttribute<T>(string serializedObject)
{
return JsonConvert.DeserializeObject<T>(serializedObject);
}
But I can't figure out why it works on my machine and not on the build server.
I'm using VS 2010, asp.net 4.0, net framework 4.0. Test framework is nunit 2.5.5
Any clues anyone?

Resources