Wire format for OpenRasta array bindings (urlencoded and multipart/formdata) - openrasta

The wire format for binding arrays and dictionaries in OpenRasta seems to be ":index" like this:
class X
{
public int[] Data { get; set; }
}
which serializes to (with two array items 5 and 12):
Data:0=5&Data:1=12
Is it possible to change this format to:
Data[0]=5&Data[1]=12
Thanks, Jørn

You can try and replace the IPathManager with a custom one that supports that format. Alternatively, feel free to add support for that format too and send a pull request to openrasta-core.

Related

ASP.NET Boilerplate: Constraining user Input DTO property value to specific set of values

I've recently started using ASP.NET Boilerplate as a starting point for a project I'm working on - Asp.NET Core Web Api + Angular, and I'm having trouble finding some information regarding something that seems to me like a common use issue. I'll try to explain what I mean the best I can.
What I want to do is to have an API endpoint that takes a parameter that needs to be restricted to a specific set of values - so, I wanted to use Enum for this purpose.
This all works nice as far as parameter validation goes, but I'm confused about how to make this work well with swagger and shared proxy generated services for fontend by Nswag.
Enum parameter is displayed as integer in the documentation parameter example, so it's not clear just by looking at the swagger documentation what is the set of available values, because int values have no meaning to the user that is looking at the documentation.
Lets use an example like this, user input used in one of app service methods:
Service method:
public async Task DoSomething(SomethingInput input)
{
//some code handling user input
}
Input DTO:
public class SomethingInput : EntityDto<string>
{
[EnumDataType(typeof(SomethingEnum))]
public SomethingEnum Something { get; set; }
public int SomeOtherData { get; set; }
}
Enum:
public enum SomethingEnum
{
Option1,
Option2,
Option3
}
In this case, available values for SomethingEnum in SomethingInput will be shown as 0, 1, 3, instead of "Option1", "Option2", "Option2".
I tried using DescribeAllEnumsAsStrings for swagger generation options which helps with the documentation, but it creates an issue in the Angular project functionality - to be specific, changing tenant fails because of the way enums are generated using DescribeAllEnumsAsStrings by Nswag tool - it expects values to be integers, rather than strings.
export enum IsTenantAvailableOutputState {
Available = <any>"Available",
InActive = <any>"InActive",
NotFound = <any>"NotFound",
}
Response value returned by API is numeric, and this code doesn't know how to parse the value correctly anymore because enum no longer has integer values:
export class AppTenantAvailabilityState {
static Available: number = IsTenantAvailableOutputState._1;
static InActive: number = IsTenantAvailableOutputState._2;
static NotFound: number = IsTenantAvailableOutputState._3;
}
The question here is, what is the best practice for having these kind of restrained parameters in routes or DTO objects used as user inputs, so that they are correctly displayed in swagger doc, and do not break down anything in angular project when regenerating shared proxies with Nswag tool?
I believe that instead of DescribeAllEnumsAsStrings() you need to add the StringEnumConverter to the SerializerSettings. In other words in ConfigureServices() in Startup.cs you should have something like this:
services
.AddMvc(options => options.Filters.Add(new CorsAuthorizationFilterFactory(_defaultCorsPolicyName)))
.AddJsonOptions(options => options.SerializerSettings.Converters.Add(new StringEnumConverter()));
my english is not very good but I will try to be clear.
I Had the same problem someday I have a Enum for gender and I Wanted to display
Male and Female instead of 0 and 1 what is NSwag generates, to solve this In Angular template I made a Array in a static class that is like a copy of backend enum, and with this was able to load a Select.
Examples here
Enum in backend
public enum Sexo
{
[Description("Masculino")]
M,
[Description("Fenemino")]
F
}
Enum in angular after Nswag generates it.
export enum EstudianteDtoSexo {
_0 = 0,
_1 = 1,
}
The array in angular(That was the way for me to solve the problem)
export class SexoArray {
static Sexo = [
{ value: 0, name: 'Masculino' },
{ value: 1, name: 'Femenino'}
];
Then I fill a ng-select with the elements of SexoArray bind it like this
<div [ngClass]="(nombres.invalid && nombres.touched)?' form-group mb-4 has-error ':' form-group mb-4'">
<label class="col-form-label">{{l("Sexo")}}<span class="text-danger"> *</span> </label>
<ng-select
[(ngModel)]="estudiante.sexo"
name= "sexoSelect"
#sexoModel = "ngModel"
required>
<ng-option *ngFor="let sex of sexo" [value]="sex.value">{{sex.name}}</ng-option>
</ng-select>
<app-input-validation [input]="sexoModel"></app-input-validation>
</div>
In this example estudiante.sexo is of type EstudianteDtoSexo
I Hope this could help you.

WCF datetime format

I developed WCF service that contains so many methods and these methods return json format. My main problem is when i have datacontract member has datetime type i get in json like this /Date(1233846970110-0500)/ which is causing me issue in IOS application. How can i write a global method that converts to MM/dd/yyyy format for very call. I tried to different methods but none works when i test it, always returns the same above format.
I tried in global.ascx like this but like
private void RegisterRoutes()
{
// Create Json.Net formatter serializing DateTime using the ISO 8601 format
var serializerSettings = new JsonSerializerSettings();
serializerSettings.Converters.Add(new IsoDateTimeConverter());
var config = HttpHostConfiguration.Create().Configuration;
config.OperationHandlerFactory.Formatters.Clear();
config.OperationHandlerFactory.Formatters.Insert(0, new JsonNetMediaTypeFormatter(serializerSettings));
var httpServiceFactory = new HttpServiceHostFactory
{
OperationHandlerFactory = config.OperationHandlerFactory,
MessageHandlerFactory = config.MessageHandlerFactory
};
RouteTable.Routes.Add(new ServiceRoute("VWPM_Srv", httpServiceFactory, typeof(IVWPM_Srv)));
}
If you want to send an MM/dd/yyyy formatted string. You just make the property a string and assign the date in the MM/dd/yyyy format.
However you can also make ios accept the dates wfc send you:
json-serialized-date-passed-between-ios-and-wcf-and-vice-versa

MVC DataAnnotation Accept No Spaces

I'm developing a Login View in MVC5.
I would like to set at the ViewModel level a DataAnnotation to state the the field does NOT accept empty spaces.
Is there a Data Annotation in MVC (something like [NoSpaces] that can be used to NOT allow a string field to contain "spaces" ?
How about this:
[RegularExpression(#"^\S*$", ErrorMessage = "No white space allowed")]
Well, the simplest but robust thing I can think of is to look at how existing code works, or how existing data annotation work.
For example, let's look at the System.ComponentModel.DataAnnotations.StringLengthAttribute class.
Here's the definition only (just to keep short):
namespace System.ComponentModel.DataAnnotations
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
public class StringLengthAttribute : ValidationAttribute
{
public StringLengthAttribute(int maximumLength);
public int MinimumLength { get; set; }
public override string FormatErrorMessage(string name);
public override bool IsValid(object value);
}
}
So I would simply copy the original implementation source code from GitHub and customize it to my needs. For example, to obtain a signature like this (if I understood correctly and this is what you wanted):
public StringLengthAttribute(int maximumLength, int minLength = 0, allowEmptySpaces = true);
For more in-depth info, I would also read the Microsoft docs on the ValidationAttribute class, which is your base class for custom validation data annotations.
EDIT:
I would NOT rely on Regular Expressions to validate data in cases where I just need to exclude empty strings or strings containing only white space(s), because Regular Expressions are very expensive to process (and require a lot of memory allocation, because of an expression compiler, a state machine, etc.).
If this is convenient for anyone, I got pass this issue by doing this on the client:
//trim each form input
var $form = $("#myForm");
$form.find("input:text").each(function(){
var $self= $(this);
$self.va($self.val().trim());
});
//then validate before submit
if($form.valid()){ $form.submit(); }
// on the server ModelState.Isvalid does verify each item with [Required] and won't accept only white spaces from an input (but this means additional roundtrip to server and it's not always convenient)

Biztalk mapping Date to String

I'm working on a biztalk project and use a map to create the new message.
Now i want to map a datefield to a string.
I thought i can do it on this way with an Function Script with inline C#
public string convertDateTime(DateTime param)
{
return System.Xml.XmlConvert.ToString(param,ÿyyyMMdd");
}
But this doesn't work and i receive an error. How can i do the convert in the map?
It's a Biztalk 2006 project.
Without the details of the error you are seeing it is hard to be sure but I'm quite sure that your map is failing because all the parameters within the BizTalk XSLT engine are passed as strings1.
When I try to run something like the function you provided as inline C# I get the following error:
Object of type 'System.String' cannot be converted to type 'System.DateTime'
Replace your inline C# with something like the following:
public string ConvertDateTime(string param1)
{
DateTime inputDate = DateTime.Parse(param1);
return inputDate.ToString("yyyyMMdd");
}
Note that the parameter type is now string, and you can then convert that to a DateTime and perform your string format.
As other answers have suggested, it may be better to put this helper method into an external class - that way you can get your code under test to deal with edge cases, and you also get some reuse.
1 The fact that all parameters in the BizTalk XSLT are strings can be the source of a lot of gotchas - one other common one is with math calculations. If you return numeric values from your scripting functoids BizTalk will helpfully convert them to strings to map them to the outbound schema but will not so helpfully perform some very random rounding on the resulting values. Converting the return values to strings yourself within the C# will remove this risk and give you the expected results.
If you're using the mapper, you just need a Scripting Functiod (yes, using inline C#) and you should be able to do:
public string convertDateTime(DateTime param)
{
return(param.ToString("YYYYMMdd");
}
As far as I know, you don't need to call the System.Xml namespace in anyway.
I'd suggest
public static string DateToString(DateTime dateValue)
{
return String.Format("{0:yyyyMMdd}", dateValue);
}
You could also create a external Lib which would provide more flexibility and reusability:
public static string DateToString(DateTime dateValue, string formatPicture)
{
string format = formatPicture;
if (IsNullOrEmptyString(formatPicture)
{
format = "{0:yyyyMMdd}";
}
return String.Format(format, dateValue);
}
public static string DateToString(DateTime dateValue)
{
return DateToString(dateValue, null);
}
I tend to move every function I use twice inside an inline script into an external lib. Iit will give you well tested code for all edge cases your data may provide because it's eays to create tests for these external lib functions whereas it's hard to do good testing on inline scripts in maps.
This blog will solve your problem.
http://biztalkorchestration.blogspot.in/2014/07/convert-datetime-format-to-string-in.html?view=sidebar
Regards,
AboorvaRaja
Bangalore
+918123339872
Given that maps in BizTalk are implemented as XSL stylesheets, when passing data into a msxsl scripting function, note that the data will be one of types in the Equivalent .NET Framework Class (Types) from this table here. You'll note that System.DateTime isn't on the list.
For parsing of xs:dateTimes, I've generally obtained the /text() node and then parse the parameter from System.String:
<CreateDate>
<xsl:value-of select="userCSharp:GetDateyyyyMMdd(string(s0:StatusIdChangeDate/text()))" />
</CreateDate>
And then the C# script
<msxsl:script language="C#" implements-prefix="userCSharp">
<![CDATA[
public System.String GetDateyyyyMMdd(System.String p_DateTime)
{
return System.DateTime.Parse(p_DateTime).ToString("yyyyMMdd");
}
]]>

ASP.NET MVC: dealing with Version field

I have a versioned model:
public class VersionedModel
{
public Binary Version { get; set; }
}
Rendered using
<%= Html.Hidden("Version") %>
it gives:
<input id="Version" name="Version" type="hidden" value=""AQID"" />
that looks a bit strange. Any way, when the form submitted, the Version field is always null.
public ActionResult VersionedUpdate(VersionedModel data)
{
...
}
How can I pass Version over the wire?
EDIT:
A naive solution is:
public ActionResult VersionedUpdate(VersionedModel data)
{
data.Version = GetBinaryValue("Version");
}
private Binary GetBinaryValue(string name)
{
return new Binary(Convert.FromBase64String(this.Request[name].Replace("\"", "")));
}
Related posts I found.
Link
Suggests to turn 'Binary Version' into 'byte[] Version', but some commenter noticed:
The problem with this approach is that
it doesn't work if you want to use the
Table.Attach(modified, original)
overload, such as when you are using a
disconnected data context.
Link
Suggests a solution similar to my 'naive solution'
public static string TimestampToString(this System.Data.Linq.Binary binary)
{ ... }
public static System.Data.Linq.Binary StringToTimestamp(this string s)
{ ... }
http://msdn.microsoft.com/en-us/library/system.data.linq.binary.aspx
If you are using ASP.Net and use the
SQL Server "timestamp" datatype for
concurrency, you may want to convert
the "timestamp" value into a string so
you can store it (e.g., on a web
page). When LINQ to SQL retrieves a
"timestamp" from SQL Server, it stores
it in a Binary class instance. So you
essentially need to convert the Binary
instance to a string and then be able
to convert the string to an equivalent
Binary instance.
The code below provides two extension
methods to do this. You can remove the
"this" before the first parameter if
you prefer them to be ordinary static
methods. The conversion to base 64 is
a precaution to ensure that the
resultant string contains only
displayable characters and no escape
characters.
public static string ConvertRowVersionToString(this Binary rowVersion) {
return Convert.ToBase64String(rowVersion.ToArray());
}
public static Binary ConvertStringToRowVersion(this string rowVersion) {
return new Binary(Convert.FromBase64String(rowVersion));
}
I think the problem with not seeing it in the bound model on form submission is that there is no Convert.ToBinary() method available to the model binary to restructure the data from a string to it's binary representation. If you want to do this, I think that you'll need to convert the value by hand. I'm going to guess that the value you are seeing is the Base64 encoding of the binary value -- the output of Binary.ToString(). In that case, you'll need to convert it back from Base64 to a byte array and pass that to the Binary() constructor to reconstitute the value.
Have you thought about caching the object server-side, instead? This could be a little tricky as well as you have to detach the object from the data context (I'm assuming LINQ) or you wouldn't be able to reattach it to a different data context. This blog entry may be helpful if you decide to go that route.
You may need to use binding to get a strongly-typed parameter to your action method.
Try rendering using:
<%=Html.Hidden("VersionModel.Version")%>
And defining your action method signature as:
public ActionResult VersionedUpdate([Bind(Prefix="VersionModel")] VersionedModel data)
{
...
}
This post http://forums.asp.net/p/1401113/3032737.aspx#3032737 suggests to use
LinqBinaryModelBinder from http://aspnet.codeplex.com/SourceControl/changeset/view/21528#338524.
Once registered
protected void Application_Start()
{
ModelBinders.Binders.Add(typeof(Binary), new LinqBinaryModelBinder());
}
the binder will automatically deserialize Version field
public ActionResult VersionedUpdate(VersionedModel data)
{ ... }
rendered this way:
<%= Html.Hidden("Version") %>
(See also http://stephenwalther.com/blog/archive/2009/02/25/asp.net-mvc-tip-49-use-the-linqbinarymodelbinder-in-your.aspx)
There are many ways like here
byte[] b = BitConverter.GetBytes(DateTime.Now.Ticks);//new byte [(DateTime.Now).Ticks];
_store.Version = new System.Data.Linq.Binary(b)
(make sure you bind exclude your version),
But the best way is to let the DB handle it...
There are many ways like here
byte[] b = BitConverter.GetBytes(DateTime.Now.Ticks);//new byte [(DateTime.Now).Ticks]; _store.Version = new System.Data.Linq.Binary(b)
(make sure you bind exclude your version),
But the best way is to let the DB handle it...

Resources