I've got a Fitnesse RowFixture that returns a list of business objects. The object has a field which is a float representing a percentage between 0 and 1. The consumer of the business object will be a web page or report that comes from a designer, so the formatting of the percentage will be up to the designer rather than the business object.
It would be nicer if the page could emulate the designer when converting the number to a percentage, i.e. instead of displaying 0.5, it should display 50%. But I'd rather not pollute the business object with the display code. Is there a way to specify a format string in the RowFixture?
You certainly don't want to modify your Business Logic just to make your tests look better. Good news however, there is a way to accomplish this that is not difficult, but not as easy as passing in a format specifier.
Try to think of your Fit Fixture as a service boundary between FitNesse and your application code. You want to define a contract that doesn't necessarily have to change if the implementation details of your SUT (System Under Test) change.
Lets look at a simplified version of your Business Object:
public class BusinessObject
{
public float Percent { get; private set; }
}
Becuase of the way that a RowFixture works we need to define a simple object that will work as the contract. Ordinarily we would use an interface, but that isn't going to serve our purpose here so a simple DTO (Data Transfer Object) will suffice.
Something Like This:
public class ReturnRowDTO
{
public String Percent { get; set; }
}
Now we can define a RowFixture that will return a list of our custom DTO objects. We also need to create a way to convert BusinessObjects to ReturnRowDTOs. We end up with a Fixture that looks something like this.
public class ExampleRowFixture: fit.RowFixture
{
private ISomeService _someService;
public override object[] Query()
{
BusinessObject[] list = _someService.GetBusinessObjects();
return Array.ConvertAll(list, new Converter<BusinessObject, ReturnRowDTO>(ConvertBusinessObjectToDTO));
}
public override Type GetTargetClass()
{
return typeof (ReturnRowDTO);
}
public ReturnRowDTO ConvertBusinessObjectToDTO(BusinessObject businessObject)
{
return new ReturnRowDTO() {Percent = businessObject.Percent.ToString("%")};
}
}
You can now change your underlying BusinessObjects around without breaking your actual Fit Tests. Hope this helps.
I'm not sure what the "polution" is. Either the requirement is that your Business Object returns a value expressed as a percentage, in which case your business object should offer that -OR- you are testing the true value of the response as float, which you have now.
Trying to get fitnesse to massage the value for readability seems a bit odd.
Related
I've defined my own struct that represents DateTime with TimeZoneInfo so I can work with UTC time while keeping the information about timezone.
I would like to get these objects with OData query, but it fails when I try to use $orderby on this properties of this type. I was able to get results when I queried $orderBy=Timestamp/Value/UniversalTime but I would like to use just $orderBy=Timestamp
Is there any possibility to order collection with this type?
public struct DateTimeWithZone : IComparable<DateTime>, IComparable<DateTimeWithZone>, IFormattable
{
private readonly DateTime _utcDateTime;
private readonly TimeZoneInfo _timeZone;
public DateTimeWithZone(DateTime dateTime, TimeZoneInfo timeZone)
{
if (timeZone == null)
{
throw new NoNullAllowedException(nameof(timeZone));
}
_utcDateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
_timeZone = timeZone;
}
...
}
With model defined like this:
public class ClientViewModel
{
public string Name { get; set; }
public DateTimeWithZone? Timestamp { get; set; }
}
And this is how it is used:
public IHttpActionResult GetAll(ODataQueryOptions<ClientViewModel> options)
{
var fromService = _clientsClient.GetAllClients().MapTo<ClientViewModel>(MappingStrategy).AsQueryable();
var totalCount = fromService.Count();
var results = options.ApplyTo(fromService); // <-- Fails here
return Ok(new PageResult<ClientViewModel>(
results as IEnumerable<ClientViewModel>,
Request.ODataProperties().NextLink,
totalCount));
}
Fails with The $orderby expression must evaluate to a single value of primitive type.
we had some similar issue with complex type ordering. Maybe this can be of assistance in your scenario as well. In our case (which is not 100% identical) we use a two phase approach:
Rewriting ODataQueryOptions
separating the extneral model (ODATA) and the internal model (EntityFramework in our case)
Rewriting ODataQueryOptions
You mention that the format $orderBy=Timestamp/Value/UniversalTime is accepted and is processed properly by ODATA. So you can rewrite the value basically by extracting the $orderby value and reinserting it with in your working format.
I described two ways on how to do this in my post Modifying ODataQueryOptions on the fly (full code included), which take existing options recreate new options by constructing a new Uri. In your case you would extract Timestamp from $orderBy=Timestamp and reinsert as with $orderBy=Timestamp/Value/UniversalTime.
Separating External and Internal Model
In addition, we used two models for the public facing API and the internal / persistence layer. On the internal side we used different properties which we grouped into a navigation property (which only exists on the public side). With this approach the user is able to specify an option via an $expand=VirtualNavigationProperty/TimeZoneInfo and $orderby=.... Internally you do not have to use the complex data type, but keep using DateTimeOffset which already holds that information. I described this separation and mapping of virtual navigation properties in the following post:
Separating your ODATA Models from the Persistence Layer with AutoMapper
More Fun with your ODATA Models and AutoMapper
According to your question it should be sufficient to rewrite the query options in the controller as you did mention that the (little bit longer) $orderby format is already working as expected and you only wanted a more convenient query syntax.
Regards, Ronald
In my ASP.NET MVC project, my actions typically call a Service layer to get data. I use the same dozen or so POCOs for all my models. I also plan on using the Service layer in console applications and maybe expose a web api at some point.
To make my database operations more efficient, my service layer only hydrates the properties in the model that are relevant to the particular method (which at this point is mostly driven by the needs of my controller actions).
So for example I might have a class Order with properties Id, Name, Description, Amount, Items. For a given service call I might only need to populate Id, Name, Items. A consumer of that service won't necessarily know that Amount is 0 only because it didn't populate the property.
Similarly, the consumer won't know whether Items is empty b/c there actually aren't any items, or whether this particular service method just doesn't populate that property.
And for a third example, say one of my views displays an ItemCount. I don't want to fully populate my Items collection, I just need an additional property on my "model". I don't want to add this property to my POCO that other service methods will be using because it's not going to be populated anywhere else.
So the natural solution is to make a POCO designed specifically for that method with only those 3 properties. That way the consumer can know that all properties will be populated with its real values. The downside to this is that I'll end writing tons of similarly shaped models.
Any advice on which method works best?
You could use Nullable Types to indicate the missing properties with a null.
For example:
class Order {
public int Id {get;set;}
public string Name {get;set;}
public string Description {get;set;}
public decimal? Amount {get;set;}
public List<Item> Items {get;set;}
}
And then if Items == null, it wasn't set. If it's an empty new List<Item>(), it's set but empty. Same for Amount. If Amount.HasValue == false, it wasn't set. If Amount.Value is 0.0d, it's set and the item is free.
Why don't you use LINQ projection?
One service method does something like:
return DbContext.Orders.Select(o => new { Id = o.Id, Name = o.Name, Description = o.Description });
while the other service method does something like:
return DbContext.Orders.Select(o => o);
I'm not sure how your application is architected, but this may be a way around creating 100's of POCO's.
Hope this helps! Good luck.
You could pass in a selector Func that returns dynamic:
public IEnumerable<dynamic> GetOrders(Func<Order, dynamic> selector) { ... }
I'm not sure how you are accessing data, but the following shows how this would work using a List<T>:
class Program
{
static void Main(string[] args)
{
var service = new Service();
var orderNames = service.GetOrders(o => new { o.Name });
foreach (var name in orderNames)
Console.WriteLine(name.Name);
Console.ReadLine();
}
}
public class Service
{
private List<Order> _orders = new List<Order>
{
new Order { Id = 1, Name = "foo", Description = "test order 1", Amount = 1.23m },
new Order { Id = 2, Name = "bar", Description = "test order 1", Amount = 3.45m },
new Order { Id = 3, Name = "baz", Description = "test order 1", Amount = 5.67m }
};
public IEnumerable<dynamic> GetOrders(Func<Order, dynamic> selector)
{
return _orders.Select(selector);
}
}
public class Order
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Amount { get; set; }
}
The use of nullable values is a good solution, however it has the downside you have no way to matk required fields. That is you cannot use a required attribute on any property. So if there is field that is obligatory in some views you have no way to represent it.
If you don't need required fileds validation this is ok. Otherwise, you need a way to represent which fileds are actually used, and then to write a custom validation provider.
A simple way to do this is to use a "Mask" class with the same property names of the original class, but with all fields boolean: a true values means the field is in use.
I used a similar solution in a system where the properties to be shown are configured in a configuration files...so it was the unique option for me since I had no possibility to represent all combination of properties. HOWEVER, I used the "Mask" class also in the View, so I was able to do all the job with just one View..with a lot of ifs.
Now if your 150 service methods and probably about 150 Views...are all different, then maybe it is simpler to use also several classes ...that is in the worst case 150 classes..the extra work to write them is negligible if compared to the effort of preparing 150 different Views.
However this doesnt mean you need 150 POCO classes. You might use an unique POCO class that is copied into an adequate class just into the presentation Layer. The advantage of this approach is that you can put different validation attributes on the various classes and you don't need to write a custom Validation provider.
Return the entire POCO with nullable types as mentioned by #sbolm. You can then create a ViewModel per MVC page view that receives a model with the specific properties it needs. This will take more performance (insignificant) and code, but it keeps your service layer clean, and keeps your views "dumb" in that they are only given what they need and have no direct relation to the service layer.
I.e. (example class from #sbolm)
class Order {
public int Id {get;set;}
public string Name {get;set;}
public string Description {get;set;}
public decimal? Amount {get;set;}
public List<Item> Items {get;set;}
}
// MVC View only needs to know the name and description, manually "map" the POCO properties into this view model and send it to the view
class OrderViewModel {
public string Name {get;set;}
public string Description {get;set;}
}
I would suggest that instead of modifying the models or creating wrapper models, you have to name the service methods such that they are self-explanatory and reveals the consumer what they returns.
The problem with the nullable approach is it makes the user to feel that the property is not required or mandatory and they try inserting instances of those types without setting those properties. Is it won't be bad having nullables every-where?
It won't be a good approach to change the domain models since all you want is just to populate some of the properties instead of that you create service with names and descriptions that are self-explanatory.
Take the Order class itself as the example, say one service method returns the Order with all the items and the other one returns only the details of the Order but not the items. Then obviously you may have to create two service methods GetOrderItems and GetOrderDetail, this sounds so simple, yes it is! but notice the service method names itself tells the client what it is going to return. In the GetOrderDetail you can return an empty items or null (but here I suggest a null) that doesn't matter much.
So for new cases you don't need to frequently change the models but all you got to do is add or remove the service methods and that's fine. Since you are creating a service you can create a strong documentation that says what method does what.
I would not performance optimize this to much unless you realy get performance problems.
I would only distinguish between returning a flat object and an object with a more complete object graph.
I would have methods returning flat objects called something like GetOrder, GetProduct.
If more complete object graphs are requested they would be called : GetOrderWithDetails.
Do you use the POCO classes for the typed views? If yes: try to make new classes that serve as dedicated ViewModels. These ViewModels would contain POCO classes. This will help you keeping the POCO classes clean.
To expand on the nullable idea, you could use the fluentvalidation library to still have validation on the types dependent on whether they are null or not. This would allow you to have a field be required as long as it was not null or any other validation scheme you can think of. Example from my own code as I had a similar requirement:
Imports FluentValidation
Public Class ParamViewModelValidator
Inherits AbstractValidator(Of ParamViewModel)
Public Sub New()
RuleFor(Function(x) x.TextBoxInput).NotEmpty.[When](Function(x) Not (IsNothing(x.TextBoxInput)))
RuleFor(Function(x) x.DropdownListInput).NotEmpty.[When](Function(x) Not (IsNothing(x.DropdownListInput)))
End Sub
End Class
recently i've decided to use viewmodels instead of EF EntityObjects.
i'm sure that there will be no problems for GET requests but i want to know what to do with create and update actions.
i've read a lot of discussions and decided that i'll act int this way.
but another questions appeared:
1) when i was using EF EntityObjects with annotations the validation logic was stored in one place, but if i have different viewmodels in different projects, then i'll have to duplicate validation rules. isn't it violation of the DRY principle?
2) i've read several posts about viewmodels and validation where people suggest to validate input in viewmodels and business rules in domain models but i can't realize how can i call validation that is defined in domain models if my actions have viewmodels as parameters:
public class MyDomainModel : IValidatableObject
{
public string Title;
// validation of business rules
}
public class MyViewModel
{
[Required]
public string Title;
}
public ActionResult Edit(MyViewModel item)
{
if (ModelState.IsValid) // MyViewModel's rules are validated not MyDomainModel's
{
...
}
If you switch to ViewModels you should let the framework perform validation via DataAttributes in your ViewModel classes. That is just a formal check on input, then you should validate according to your business rules (sometimes with just data annotations is just impossible to cover al the scenarios), and in case of errors, add them to the modelstate.
Example:
public class MyViewModel
{
[Required]
[StringLength(20)]
[RegularExpression("whatever")]
public string Foo { get; set; }
[Required]
public int Bar { get; set; }
public bool AFlagNotModifiableButImportant { get; set; }
}
in your Post Action you can do something like:
public ActionResult Sample (MyViewModel Obj)
{
if (!ModelState.IsValid) {
return View(Obj);
}
// Complex business logi checks in here
MyBusinessObj BsnObj = new MyBusinessObj(Obj);
if (!BsnObj.IsValid()) {
ModelState.AddModelError(string.Empty, "A veery bad error");
return View(Obj);
}
// Perform Heavy Business Logic which creates a new ViewModel (eg. setting the flag property in order to show something important at view level)
MyViewModel NewOne = BsnObj.DoIt();
// Return a view with the new Model (can be whatever you want)
return View(NewOne);
}
Obviously I'm keeping it very simple.
Following this pattern sure add a little overhead in term of code, but checks have to be done both client side (just a formal validation on input) and server side (both formal and semantic validation). I prefer to have all semantics in a business assembly, leaving formal checks to the MVC unobtrusive validation engine (just some UI sugar in my views, yes, I hate Javascript) .
Usually my Business Objects use ViewModel's properties considering them readonly (just the usefull ones to prevent bad injections) and do the dirty/heavy job.
This may not be the perfect solution for everything, but I've noticed that applying this pattern (and force other member of the team to do the same), is leading to a good codebase.
Yes, we're still far from perfection, I'd like to write both semantics and formal checks just once, but that's how web is working right now.
Let me know if you need further advice or if I've completely misunderstood your question.
PS: once you choose a pattern, stick to it no matter what.
EDIT: (long comments are a no no)
In the constructor I usually apply mappings on fields I need to change, I try to consider the ViewModel properties as readonly, to avoid unwanted modifications.
My IsValid() method just holds business checks (for example, given an ID it checks for real existence in a certain table or given a username checks if he can actually access certain data).
It's just a separation between ViewModel validation (for me is just syntactic => strings are strings, integer are integer, positive numbers are >= 0, string lengths are respected, ranges are met and so on) and real business validity (semantic => a user can access some data, an object is valid in the scope of the application).
Of course the Business validation layer can also be simple (or not exists at all), I prefer to keep them separated for reusability (often my business logic is shared between an MVC application and a WPF application). It's a bit of extra work but on the long run it pays better, I can use my complex business logic everywhere. (and working with Banks, it's the greatest goal. Change logic in just one assembly, for instance to add a new check on something, and being confident that each application using that assembly will be up to date).
So definitely is a more of extrawork, but I think it's better investing a few dev hours before than wasting days lately for maintenance/evolutions.
Nowadays programming seems reduced to a go-and-forget activity, (due to reduce time/budget or simply because we do our task and then change employee), but each line that is coded, will need some kind of maintenance in the future, so it's better to keep things ordered and clean, preferring maintenance ease against developing speed.
I have a custom viewmodel which serialized using a JsonResult. The ViewModel has some properties which have to be public, but at the same time these properties should not be visible in the resulting Json output.
I've already tried using the [NonSerialized] attribute, but that did not seem to have any effect.
Is there any simple way to do this? Or would I have to code my own result type (in which case I probably won't bother)?
You can put a [ScriptIgnore] attribute on the members that shouldn't be serialized. See ScriptIgnoreAttribute Class in MSDN for an example.
Just create an interface to return instead of a class.
public interface IMyViewModel {
string MyPublicProperty { get; set; }
}
Then create a class that inherits the interface
public class MyViewModel : IMyViewModel {
public string MyPublicProperty { get; set; }
public string MyNotSoPublicProperty { get; set; }
}
And return the interface, not the class, in the Controller Action
public JsonResult MyJson(){
IMyViewModel model = new MyViewModel();
return Json(model);
}
And the resulting JSON will be
{
'MyPublicProperty': ''
}
One of the challenges in client-side scripting is, that if you're changing your classes, you have no idea whether you're destroying the client-side implementation or not. If you use interface types in your JSON, you understand that if you change the interface, you're doing something that potentially may be killing the client side implementation. And it also saves you from double-checking the client side in vain if you're changing something that is NOT in the inteface (thus not being serialized).
Also, many times, your ViewModels might have large collections or complex types in them that you don't necessarily want to output to the client. These might take a long time to serialize or expose information that simply does not belong into the client code. Using interfaces will make it more transparent to know what is being in the output.
Also, using attributes such as [ScriptIgnore] on a property only applies to a specific scenario (JavaScript Serialization) forcing you to face the exact same problem if you're later serializing to XML for example. This would unnecessarily litter your viewmodels with tons of attributes. How many of them you really want in there? Using intefaces applies anywhere and no viewmodel needs to be littered with extra attributes.
Have a look at JSON.NET from James Newton-King. It'll do what you're looking for.
Extend the JavaScriptConverter class to not include properties with the NonSerializedAttribute. Then you can create a custom ActionResult that uses your JavaScriptConverter to serialize the object.
This creates a solid and testable class without having to (re)generate wrapper classes or using anonymous objects.
You can create a wrapper class that exposes only those properties that you want in the JsonResult. In the example below, Cow has 2 properties - "Leg" and "Moo". Suppose you want to only expose "Leg" as a property. Then
Dim cw as CowWrapper = New CowWrapper(c)
will return a wrapper class that only exposes "Leg". This is also useful for things like DataGridView if you only want to display some subset of the properties.
Public Class Cow
Public ReadOnly Property Leg() as String
get
return "leg"
end get
end Property
Public ReadOnly Property Moo() as String
get
return "moo"
end get
end Property
end class
Public Class CowWrapper
Private m_cow as Cow = Nothing
Public Sub New(ByVal cow as Cow)
m_cow = cow
end Sub
m_cow = cow
Public ReadOnly Property Leg() as String
get
return m_cow.Leg()
end get
end Property
end Class
Not exactly the answer you're looking for, but you can cheat Json() using the following code and anonymous classes:
MyModel model = ...;
return Json(new MyModel {model.Prop1, model.Prop2});
I needed the answer to this for ASP.NET Core 6.x and couldn't find it.
I finally found the answer and it is :
[System.Text.Json.Serialization.JsonIgnore]
Here's an example in a class
class Sample{
// Item will not be serialized
[System.Text.Json.Serialization.JsonIgnore]
String Item{get;set;}
// Count will be serialized
int Count{get;set;}
}
I'm following Steve Sanderson's example from this ASP.NET MVC book on creating a model by hand instead of using diagramming tools to do it for me. So in my model namespace I place a class called MySystemModel with something like the following in it
[Table(Name="tblCC_Business")]
public class Business
{
[Column(IsPrimaryKey=true, IsDbGenerated=false)]
public string BusinessID { get; set; }
// this is done because Business column and Business have interfering names
[Column(Name="Business")] public string BusinessCol { get; set; }
}
This part of it is all fine. The problem however is returning multiple result sets from a stored procedure, but mixing and matching SQL with LINQ modelling. We do this because the LINQ to SQL translation is too slow for some of our queries (there's really no point arguing this point here, it's a business requirement). So basically I use actual SQL statements along with my LINQ models in my "repository" like so:
public IEnumerable<MyType> ListData(int? arg)
{
string query = "SELECT * FROM MyTable WHERE argument = {0}";
return _dc.ExecuteQuery<MyType>(query, arg);
//c.GetTable<MyType>(); <-- this is another way of getting all data out quickly
}
Now the problem I'm having is how to return multiple result sets as I'm not extending DataContext, like so:
public ContractsControlRepository()
{
_dc = new DataContext(ConfigurationManager.ConnectionStrings["MyConnectionString"].ToString());
}
This link describes how multiple result sets are returned from stored procedures.
[Function(Name="dbo.VariableResultShapes")]
[ResultType(typeof(VariableResultShapesResult1))]
[ResultType(typeof(VariableResultShapesResult2))]
public IMultipleResults VariableResultShapes([Parameter(DbType="Int")] System.Nullable<int> shape)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), shape);
return ((IMultipleResults)(result.ReturnValue));
}
So how do I turn this into something that can be used by my repository? I just need to be able to return multiple result sets from a repository which contains DataContext, and doesn't extend it. If you copied and pasted the previous extract into a repository like I've got it will just state how ExecuteMethodCall isn't available, but that's only available if you extend DataContext.
Resources
Guy Berstein's Blog
Every time I ask a question that has been hindering me for days on end I end up finding the answer within minutes. Anyway, the answer to this issue is that you have to extend DataContext in your repository. If like me you're worried about having to specify the connection string in every single controller then you can change the constructor in the repository class to something like this:
public ContractsControlRepository()
: base(ConfigurationManager.ConnectionStrings["AccountsConnectionString"].ToString()) { }
This way when you instantiate your repository the connection is set up for you already, which gives you less to worry about, and actually centralizes specifying the connection string. Extending DataContext also means you have access to all of the protected methods such as ExecuteMethodCall used for calling stored procedures and bringing back, if you will, multiple result sets.