I have a website that reads some of its content from a database, I need this website in both languages, English and Arabic.
the needed content is duplicated in the database in both languages. lets say I have a En_Name and Ar_Name columns in my database.
and for example for the Arabic version of the website a link will display a text from Ar_Name , and with the English one it should display the text from the En_Name.
for the static content in my website I think it is a good idea to use the ASP.NET default localization using (.resx files). but what I don't know is how to do the localization for the dynamic section of the website.
So, how can I make the same hyperlink read once from the Ar_Name field, and then from the En_Name based on the users choice (Localization)?
There are many ways to accomplish this. You've not mentioned which database technology you are using, so my example is with Entity Framework. You may need to customise this to your own situation.
Something similar may be possible with LinqToSql or other ORMs. If you are using something else entirely, then the key is to have a central class that you pass something consistent to (hence the interface) that does the translation.
For example, if I was using Entity Framework, every table in the database that had these two fields I'd add an interface that exposes those fields. Then I'd have a helper class with a method that took any entity with that interface and checked the current localisation and return the correct version of the text.
public interface IBilingualEntity
{
// Defines a consistent interface that indicates which language version
// each thing is in.
string Ar_Name { get; }
string En_Name { get; }
}
public partial MyEntity : IBilingualEntity
{
// This is a class generate by Entity Framework. But it could
// be anything really if you are using some other framework.
//
// Nothing to do here as the other side of the partial
// should already implement the interface with the code
// generated from Entity Framework. If not, implement the
// interface and return the correct language version in
// the property.
}
// This is the helper that works out which language version to use.
public class BilingualHelper
{
public string GetName(IBilingualEntity entity)
{
// NOTE: You may have to strip away the region part of the name
// but off the top of my head I can't remember the format.
// If you are using something else to store the culture you'll
// have to reference that instead.
var cultureName = Thread.CurrentThread.CurrentUICulture.Name;
if (cultureName == "ar")
return entity.Ar_Name;
return entity.En_Name;
}
}
Related
I'm using Entity Framework (DB First) on a new project and wanted to add some customisation to the classes generated. However, my changes are obviously lost every time that the edmx is refreshed. I was just wondering if there is a design pattern for handling this sort of thing?
As an example, suppose I have a class with a integer property; StatusID - and I'd like to extend the entity class so that the status value can also be accessed/set via the related enum and finally a property that gets a text representation of that Enum from the description attribute. This all works, but those customisations are lost when the model is refreshed. I appreciate that the property can be converted to an enum, so the latter property that gets the description of the enum is perhaps a better example for this question.
I think I know the answer but I just wanted to put this out there in case there were some magic tricks that would allow this to work and prevent those customisations from being lost.
public int StatusID { get; set; }
public Enumerations.ValidationStatus StatusEnum
{
get
{
return (Enumerations.ValidationStatus)StatusID;
}
set
{
StatusID = (int)value;
}
}
public string StatusText
{
get
{
return MyMethodThatGetsTheEnumDescription(StatusEnum);
}
}
Two Solutions to work around the problem:
User Data Transfer Object(DTO) nd put the enum there. then use Automapper or manually map between the DB Model and the DTO Model (best practice)
Instead of enum you can use extension functions on the model and define your getter, setters and any extra properties you want as extension functions to the class
(will add some complexity to your models)
I need to port a website to asp.net and decided to use Umbraco as the underlying CMS.
The issue I'm having is I need to retain the URL structure of the current site.
The current URL template looks like the following
domain.com/{brand}/{product}
This is hard to make a route for since it mixes in with all the other content on the site. Like domain.com/foo/bar which is not a brand or product.
I've coded up a IContentFinder, and injected it into the Umbraco pipeline, that check the URL structure and determins if domain.com/{brand} matches any of the known brands on the site, in which case i find the content by its internal route domain.com/products/ and pass along {brand}/{model} as HttpContext Items and return it using the IContentFinder.
This works, but it also means no MVC controller is called. So now I'm left with fetching from the database in the cshtml file which is not so pretty and kind of breaks MVC conventions.
What i really wan't is to take the url domain.com/{brand}/{product} and rewrite it to domain.com/products/{brand}/{product} and then being able to hit a ProductsController serving up the content based on the parameters brand and product.
There are a couple of ways to do this.
It depends a bit on your content setup. If your products exist as pages in Umbraco, then I think you are on the right path.
In your content finder, remember to set the page you've found on the request like this request.PublishedContent = content;
Then you can take advantage of Route Hijacking to add a ProductController that will get called for that request: https://our.umbraco.org/Documentation/Reference/Routing/custom-controllers
Example implementation:
protected bool TryFindContent(PublishedContentRequest docReq, string docType)
{
var segments = docReq.Uri.GetAbsolutePathDecoded().Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
string[] exceptLast = segments.Take(segments.Length - 1).ToArray();
string toMatch = string.Format("/{0}", string.Join("/", exceptLast));
var found = docReq.RoutingContext.UmbracoContext.ContentCache.GetByRoute(toMatch);
if (found != null && found.DocumentTypeAlias == docType)
{
docReq.PublishedContent = found;
return true;
}
return false;
}
public class ProductContentFinder : DoctypeContentFinderBase
{
public override bool TryFindContent(PublishedContentRequest contentRequest)
{
// The "productPage" here is the alias of your documenttype
return TryFindContent(contentRequest, "productPage");
}
}
public class ProductPageController : RenderMvcController {}
In the example the document type has an alias of "productPage". That means that the controller needs to be named exactly "ProductPageController" and inherit the RenderMvcController.
Notice that it does not matter what the actual pages name is.
I have a web solution (in VS2010) with two sub-projects:
Domain which holds the Model classes (mapped to database tables via Entity Framework) and Services which (besides other stuff) are responsible for CRUD operations
WebUI which references the Domain project
For the first pages I've created I have used the Model classes from the Domain project directly as Model in my strongly typed Views because the classes were small and I wanted to display and modify all properties.
Now I have a page which should only work with a small part of all properties of the corresponding Domain Model. I retrieve those properties by using a projection of the query result in my Service class. But I need to project into a type - and here come my questions about the solutions I can think of:
I introduce ViewModels which live in the WebUI project and expose IQueryables and the EF data context from the service to the WebUI project. Then I could directly project into those ViewModels.
If I don't want to expose IQueryables and the EF data context I put the ViewModel classes in the Domain project, then I can return the ViewModels directly as result of the queries and projections from the Service classes.
In addition to the ViewModels in the WebUI project I introduce Data transfer objects which move the data from the queries in the Service classes to the ViewModels.
Solution 1 and 2 look like the same amount of work and I am inclined to prefer solution 2 to keep all the database concerns in a separate project. But somehow it sounds wrong to have View-Models in the Domain project.
Solution 3 sounds like a lot more work since I have more classes to create and to care about the Model-DTO-ViewModel mapping. I also don't understand what would be the difference between the DTOs and the ViewModels. Aren't the ViewModels exactly the collection of the selected properties of my Model class which I want to display? Wouldn't they contain the same members as the DTOs? Why would I want to differentiate between ViewModels and DTO?
Which of these three solutions is preferable and what are the benefits and downsides? Are there other options?
Thank you for feedback in advance!
Edit (because I had perhaps a too long wall of text and have been asked for code)
Example: I have a Customer Entity ...
public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public City { get; set; }
// ... and many more properties
}
... and want to create a View which only shows (and perhaps allows to edit) the Name of customers in a list. In a Service class I extract the data I need for the View via a projection:
public class CustomerService
{
public List<SomeClass1> GetCustomerNameList()
{
using (var dbContext = new MyDbContext())
{
return dbContext.Customers
.Select(c => new SomeClass1
{
ID = c.ID,
Name = c.Name
})
.ToList();
}
}
}
Then there is a CustomerController with an action method. How should this look like?
Either this way (a) ...
public ActionResult Index()
{
List<SomeClass1> list = _service.GetCustomerNameList();
return View(list);
}
... or better this way (b):
public ActionResult Index()
{
List<SomeClass1> list = _service.GetCustomerNameList();
List<SomeClass2> newList = CreateNewList(list);
return View(newList);
}
With respect to option 3 above I'd say: SomeClass1 (lives in Domain project) is a DTO and SomeClass2 (lives in WebUI project) is a ViewModel.
I am wondering if it ever makes sense to distinguish the two classes. Why wouldn't I always choose option (a) for the controller action (because it's easier)? Are there reasons to introduce the ViewModel (SomeClass2) in addition to the DTO (SomeClass1)?
I would solve your problem by using an auto-mapping tool (like AutoMapper) to do the mapping for you. In cases where the mapping is easy (for example if all properties from one class should be mapped to properties with the same name on another class) AutoMapper will be able to do all the hook-up work for you, and you'll have to give a couple of lines of code to note that there should be a map between the two at all.
That way, you can have your entities in Domain, and a couple of view model classes in your WebUI, and somewhere (preferrably in WebUI or a sub namespace of the same) define maps between them. Your view models will in effect be DTOs, but you won't have to worry much about the conversion process between the domain and your DTO classes.
Note: I would strongly recommend against giving your Domain entities straight to the views of your MVC web UI. You don't want EF to "stick around" all the way to the front-end layer, in case you later want to use something other than EF.
introduce ViewModels which live in the
WebUI project and expose IQueryables
and the EF data context from the
service to the WebUI project. Then I
could directly project into those
ViewModels.
The trouble with this is you soon run into problems using EF trying to 'flatten' models. I encountered something similar when I had a CommentViewModel class that looked like this:
public class CommentViewModel
{
public string Content { get; set; }
public string DateCreated { get; set; }
}
The following EF4 query projection to the CommentViewModel wouldn't work as the couldn't translate the ToString() method into SQL:
var comments = from c in DbSet where c.PostId == postId
select new CommentViewModel()
{
Content = c.Content,
DateCreated = c.DateCreated.ToShortTimeString()
};
Using something like Automapper is a good choice, especially if you have a lot of conversions to make. However, you can also create your own converters that basically convert your domain model to your view model. In my case I created my own extension methods to convert my Comment domain model to my CommentViewModel like this:
public static class ViewModelConverters
{
public static CommentViewModel ToCommentViewModel(this Comment comment)
{
return new CommentViewModel()
{
Content = comment.Content,
DateCreated = comment.DateCreated.ToShortDateString()
};
}
public static IEnumerable<CommentViewModel> ToCommentViewModelList(this IEnumerable<Comment> comments)
{
List<CommentViewModel> commentModels = new List<CommentViewModel>(comments.Count());
foreach (var c in comments)
{
commentModels.Add(c.ToCommentViewModel());
}
return commentModels;
}
}
Basically what I do is perform a standard EF query to bring back a domain model and then use the extension methods to convert the results to a view model. For example, the following methods illustrate the usage:
public Comment GetComment(int commentId)
{
return CommentRepository.GetById(commentId);
}
public CommentViewModel GetCommentViewModel(int commentId)
{
return CommentRepository.GetById(commentId).ToCommentViewModel();
}
public IEnumerable<Comment> GetCommentsForPost(int postId)
{
return CommentRepository.GetCommentsForPost(postId);
}
public IEnumerable<CommentViewModel> GetCommentViewModelsForPost(int postId)
{
return CommentRepository.GetCommentsForPost(postId).ToCommentViewModelList();
}
Talking about Models, ViewModels and DTOs is confusing, personally I don't like to use these terms. I prefer to talk about Domain Entities, Domain Services, Operation Input/Result (aka DTOs). All of these types live in the Domain layer. Operations is the behavior of Entities and Services. Unless you are building a pure CRUD application the presentation layer only deals with Input/Result types, not Entities. You don't need additional ViewModel types, these are the ViewModels (in other words, the Model of the View). The View is there to translate the Operation Results to HTML, but the same Result could be serialized as XML or JSON. What you use as ViewModel is part of the domain, not the presentation layer.
I am wondering if there is a best practice for creating a REST API with ASP.NET MVC 3? At the moment I am thinking of creating a controller for each version of the REST API. For example, so far I have:
public class V1Controller : Controller
{
public V1Controller()
{
}
public ActionResult GetUser(string userId, IUserRepository userRepostory)
{
//code to pull data and convert to JSON string
return View("Results");
}
public ActionResult GetUsersByGroup(string groupId, IUserRepository userRepostory)
{
//code to pull data and convert to JSON string
return View("Results");
}
}
Then for the views I overwrite the _ViewStart.cshtml to remove the layout and then I have Results.cshtml that just outputs the data that is formatted in the controller action, right now JSON. Having every single REST call in one controller seems like a bit too much but it is the best way I can think of so that I can keep clean separate versions of the API so that when it comes to creating version 2 of the API, I can create a V2Controller and not break the existing API to give people time to switch over to the new API.
Is there a better way to create a REST API with ASP.NET MVC 3?
I was able to find a decent solution using MVC's use of Areas.
First, I wanted to have my API follow this URL Definition:
http://[website]/[major_version]_[minor_version]/{controller}/{action}/...
I also wanted to break up the different versions in separate Project files and use the same Controller names in each version:
"../v1_0/Orders/ViewOrders/.." => "../v2_3/Orders/ViewOrders/.."
I searched around and found a workable solution with the use of MVC Areas.
I created a new project in my solution called "Api.Controllers.v1_0" and, as a test, put a SystemController.cs file in there:
using System.Web.Mvc;
namespace Api.Controllers.v1_0
{
public class SystemController : Controller
{
public ActionResult Index()
{
return new ContentResult() {Content = "VERSION 1.0"};
}
}
}
I then added a v1_0AreaRegistration.cs file:
using System.Web.Mvc;
namespace Api.Controllers.v1_0
{
public class v1_0AreaRegistration : AreaRegistration
{
public override string AreaName
{
get{ return "v1_0";}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"v1_0",
"v1_0/{controller}/{action}/{id}",
new { controller = "System", action = "Index", id = UrlParameter.Optional }
);
}
}
}
I walked through the same steps above for a "..v1_1" project with the corresponding files in there, added the projects as references into my "Api.Web" MVC project and was off and running.
If all you are returning is JSON, you do not need a view. Jusr return
new JsonResult(){Data = Data};
Look in here.
Also in terms of versioning, versions can be implemented as different controllers or as extra methods in the same controller. But without knowing why you would need versions and why your clients (which I assume are browsers) would need to know about versioning is not clear from your question.
A controller such as the one you posted in your example code should always keep that methods that you have now for instance GetUsersByGroup() with the same signature. I don't see how there could be a different version of that method.
The inputs are group and repository (which I believe comes from DI). The output is a list of users in JSON format. That's all that matters to the users of the API. What you do inside this method is no one's business.
You should think more of inputs and outputs. You shouldn't be changing the signatures of existing actions unless it is really neccessary to do so.
Think of the controller class in terms of implementing the interface. You have an interface and controller class is it's implementation (I mean you don't need to have it but just think of it in that way). You will rarely change the interface once one or several classes implement it. But you might add the methods to it. And that requires only changes in implementing classes - it does not break the functionality of the API and everyone who's using it will be able to continue using it.
We are trying to design a site that will support multilingual data and we use asp.net and nhibernate for O/R mapping. After some googling we decided that for us its best to create the entity classes containing all fields we need for supporting the default (english) language and for each multilingual class we would create a new class containing only the multilingual fields plus the id of the main (english) class and the language Id. For example a simple "product" class we could have the fields :
product
int ID
string DescriptionInEnglish
string FullDescriptionInEnglish
decimal price
and a second class "product_Lang" containing
product_Lang
int Product_ID
int Language_ID
string Description
string FullDescription
then for being able to load a product in any language we could add a product_Lang property called lang on the products and for easy binding we could have two read only properties like that :
string DescriptionToBind
{
get
{
if (lang != null)
return this.lang.Description;
else
return this.DescriptionInEnglish;
}
}
string FullDescriptionToBind
{
get
{
if (lang != null)
return this.lang.FullDescription;
else
return this.FullDescriptionInEnglish;
}
}
for loading some products we can use some methods on the ProductRpository like that :
Product GetProductByID(int ID);
Product GetProductbyID_ML(int ID, int Language_ID);
and for loading some collections
IList<Product> GetAllProducts();
IList<Product> GetAllProducts_ML(Language_ID);
The problem is how to map the Lang property inside the product class in nhibernate.
It may be easy but I cannot figure out. Its not one-to-one because in english lang is optional. I thought about one-to-many so i load a list of all but i think its not fair to load all languages because i need only one.
Any help ? or any other suggestions will still give fair performance ?
I have written a detailed article about multi language implementation with ASP.NET and NHibernate.
Check Create a multi languaged domain model with NHibernate and C#