I am using database with multiple language support. Now the problem is that I need to enter my language into query in order to get information and it is fine, but what would be optimal way to store that information.
On client side it will be stored in cookies, of course. Now only way I can think of is making global variable on class and then use it in my functions. Is that only way?
Example code
private string lang = Infrastructure.UserSettings.Language(); // I don't have this implemented yet
[HttpGet]
public dynamic List()
{
string lang = "English"; // That's why I set it here manually for testing
var items = _db.Items.OrderByDescending(x => x.ID).Select(x => new
{
ID = x.ID,
Price = x.Price,
Name = x.ItemTranslations.Where(y => y.Language.Name == lang).Select(y => y.Name).SingleOrDefault(),
Category = new {
ID = x.Category.ID,
Name = x.Category.CategoryTranslations.Where(y => y.Language.Name == lang).Select(y => y.Name).SingleOrDefault()
}
});
return items;
}
My question: Is this good way of doing this or there is some more optimal way?
You could make a base controller with a read-only variable, like so:
public class BaseController : Controller
{
public string UserLanguage
{
get
{
var cLanguage = HttpContext.Request.Cookies["lang"];
if (cLanguage != null)
return cLanguage.Value;
else
return "English";
}
}
}
Then inherit your base controller, like so:
public class HomeController : BaseController
Then access your variable like so:
var items = _db.Items.OrderByDescending(x => x.ID).Select(x => new
{
ID = x.ID,
Price = x.Price,
Name = x.ItemTranslations.Where(y => y.Language.Name == UserLanguage).Select(y => y.Name).SingleOrDefault(),
Category = new {
ID = x.Category.ID,
Name = x.Category.CategoryTranslations.Where(y => y.Language.Name == lang).Select(y => y.Name).SingleOrDefault()
}
});
You would just need to set the cookie at a particular time.
A cookie is sent to the server on every page request. If the setting is available in the cookie, just read the cookie when you need to do a query. There is no performance overhead for reading a cookie that is already present.
Related
After the server returned the object, the List type field went missing.
Each EmployeeViewModel has a list of EmployeeContactViewModel objects. The intended logic is, after querying the employee object from database, populate the view model in a method, including the list, and return to client.
The view model:
public class EmployeeViewModel
{
public List<EmployeeContactViewModel> EmployeeContacts;
public EmployeeViewModel()
{
EmployeeContacts = new List<EmployeeContactViewModel>();
}
public string EmployeeId { get; set; }
public string EmployeeName { get; set; }
// more fields
}
The method to populate view models:
public EmployeeViewModel GetViewModelFromEmpObject()
{
var vm = new EmployeeViewModel();
var contact1 = this.CONTACTs.Where(e => e.ContactId == 1).FirstOrDefault();
if (contact1 != null)
{
var contactVm1 = new EmployeeContactViewModel();
CopyContactFields(contact1, contactVm1); // method to populate view-model
vm.EmployeeContacts.Add(contactVm1);
}
else
vm.EmployeeContacts.Add(new EmployeeContactViewModel());
var contact2 = this.CONTACTs.Where(e => e.ContactId == 2).FirstOrDefault();
if (contact2 != null)
{
var contactVm2 = new EmployeeContactViewModel();
CopyContactFields(contact1, contactVm2); // method to populate view-model
vm.EmployeeContacts.Add(contactVm2);
}
else
vm.EmployeeContacts.Add(new EmployeeContactViewModel());
// more lines below
}
The api controller method is below. By setting a breakpoint at the return line, I could see the EmployeeContactViewModel list was correctly created.
[HttpGet("{empid:string}")]
public async Task<EmployeeViewModel> GetAsync(string empid)
{
Employee emp = await _context.Employees
.Include(c => c.CONTACTs)
.Where(c => c.EmployeeId == empid)
.FirstOrDefaultAsync();
var viewModel = emp.GetViewModelFromEmpObject();
return viewModel;
}
However on the client side, although all the other fields (EmployeeId, EmployeeName, etc.) were present in the response, there was nothing for EmployeeContacts list, when inspecting the server response in the browser network tab.
I tried to search before asking but using "Serialize" as a keyword would just get topics on how to do serialization. Any advice is appreciated.
Do you mean that EmployeeContacts is not included in the response result?
You can install Microsoft.AspNetCore.Mvc.NewtonsoftJson, and add this line in Program.cs:
builder.Services.AddMvc().AddNewtonsoftJson(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
I'm trying to display data from a SQL Server database. I've been struggling with it for a whole day now and still can't find any working solution or tutorial.
What I want to do - make a simple "database browser". The best thing that worked so far was this tutorial https://www.c-sharpcorner.com/article/entity-framework-database-first-in-asp-net-core2/
But I have only one table to display and I don't know how to write this part of code:
public IActionResult Index()
{
var _emplst = _dbContext.tblEmployees
.Join(_dbContext.tblSkills, e => e.SkillID, s => s.SkillID,
(e, s) => new EmployeeViewModel
{ EmployeeID = e.EmployeeID, EmployeeName = e.EmployeeName,
PhoneNumber = e.PhoneNumber, Skill = s.Title,
YearsExperience = e.YearsExperience }).ToList();
IList<EmployeeViewModel> emplst = _emplst;
return View(emplst);
}
for just one table (without any join). Everything I try ends up with an error that I cannot convert tblEmployees to EmployeeViewModel.
Could someone possibly help me? Or suggest any other solution, that might work? I really just want to drag a data from a table and display it on a web page.
EDIT:
ComponentContext.cs:
public class ComponentsContext:DbContext
{
public ComponentsContext(DbContextOptions<ComponentsContext> options) : base(options)
{
}
public DbSet<tblComponents> tblComponent { get; set; }
}
}
Your _emplst list is of a different type (class) than the type (class) EmployeeViewModel.
So you need to go through you list _emplst and transfer the values needed in EmployeeViewModel.
This can be something like this:
public IActionResult Index()
{
var _emplst = _dbContext.tblEmployees.
Join(_dbContext.tblSkills, e => e.SkillID, s => s.SkillID,
(e, s) => new EmployeeViewModel
{ EmployeeID = e.EmployeeID, EmployeeName = e.EmployeeName,
PhoneNumber = e.PhoneNumber, Skill = s.Title,
YearsExperience = e.YearsExperience }).ToList();
var emplst = _emplst.Select( e=> new EmployeeViewModel {
.. i dont known the properties ..
A = e.A,
B = e.B,
... ..
}).ToList();
return View(emplst);
}
As answer to your comment below on the tlbComponent, try this:
var _cmplist = _dbContext.tblComponent.ToList().Select(e => new ComponentsViewModel { ID = e.ID, Name = e.Name, } ).ToList();
IList<ComponentsViewModel> cmplist = _cmplist;
return View(cmplist);
i have change _dbContext.tblComponent.Select(... to _dbContext.tblComponent.ToList().Select(....
I have this logic in several methods in my MVC5 project. It works but I am repeating myself pretty consistently.
private PersonnelManagementEntities db = new PersonnelManagementEntities();
private ActiveDirectoryTools adt = new ActiveDirectoryTools();
private ManagerService ms = new ManagerService();
private UserService us = new UserService();
private CompanyService cs = new CompanyService();
public ActionResult CompanySummary(int id = 0)
{
//Repeating logic begins here
int setID = 0;
adt.GetUserInfo(User.Identity.Name);
//Fetch current users company
User currentUser = us.getUser(adt.adUserName);
//Determine if user is a global manager or not. If global display all companies
ViewBag.Company = cs.FetchCompanies(currentUser);
//You can only see the companies you're assigned to, in the AllRequests window. Unless manually overwritten in the URL
if (currentUser.GlobalUser == true && id > 0)
{
setID = id;
}
else
{
setID = (int)currentUser.CompanyID;
}
//End of repeating logic
var resultSet = db.UserTimeSummaryUpdated(setID);
return View(resultSet.ToList());
}
What do you guys think would be the best way of reducing the amount of times I repeat this?
You can see here in another method where I reuse this code:
public ActionResult AllRequests(int id = 0)
{
int setID = 0;
adt.GetUserInfo(User.Identity.Name);
User currentUser = us.getUser(adt.adUserName);
ViewBag.Company = cs.FetchCompanies(currentUser);
//You can only see the companies you're assigned to, in the AllRequests window. Unless manually overwritten in the URL
if (id > 0)
{
setID = id;
}
else
{
setID = (int)currentUser.CompanyID;
}
ViewBag.EmployeeList = db.Users
.Where(x => x.disabled == false)
.Where(x => x.CompanyID == setID)
.OrderBy(x => x.FullName)
.ToList();
IQueryable timeRequests = db.TimeRequests
.Include(t => t.ApproveDenyReason)
.Include(t => t.DayType)
.Include(t => t.User)
.Include(t => t.User1)
.Include(t => t.User2)
.OrderByDescending(t => t.sDateTime)
.Where(t => t.User.CompanyID == setID);
return View(timeRequests);
}
I was thinking about creating an ActionFilter and doing it that way but it seems kind of a hack instead of the correct way of doing things.
I also entertained the idea of when a user logs in I create a user object and persist it through a session.
Any help is appreciated
One option is to write a CustomController that inherits Controller. I did this to add Member Session Data and a Messaging Output System that can write to my LayoutView. For the example below I assumed FetchCompanies returns a list...
public class CustomController : Controller
{
private ActiveDirectoryTools _adt = new ActiveDirectoryTools();
private UserService _us = new UserService();
private CompanyService _cs = new CompanyService();
public List<Company> UserCompanies;
public ApplicationController()
: base()
{
_adt.GetUserInfo(User.Identity.Name);
User currentUser = _us.getUser(adt.adUserName);
UserCompanies = _cs.FetchCompanies(currentUser);
}
}
When you create your Controller inherit from this CustomController. Then in your ActionResult simply set using UserCompanies.
public AccountController:CustomController
{
public ActionResult Index()
{
ViewBag.Company = UserCompanies;
return View();
}
}
im trying to answer a Get Request in My Web Api with a JSON File in a poll application. When a user of my application uses a token, I want to response a PollParticipation object, which contains a a poll, a list of the options of the poll, a list of my UserPollOptions (The connection between the UserPoll and the Option) and a List with lists of userPollOption with the answers of other participants.
The problem is that I am receiving a HTTP Error 502.3 - Bad Gateway and I don't know why. Here is my code:
[HttpGet("{token}")]
[Route("pollway/{token}")]
public PollParticipation Participate(string token)
{
PollParticipation myPoll = new PollParticipation();
if (!_dbContext.UserPollModels.Any(u => u.UserPollToken == token))
{
return new PollParticipation();
}
UserPollModel userPoll = _dbContext.UserPollModels.FirstOrDefault(u => u.UserPollToken == token);
PollModel thisPoll = _dbContext.PollModels.FirstOrDefault(u => u.PollId == userPoll.PollId);
myPoll.poll = thisPoll;
// List of all Options
List<OptionModel> options = new List<OptionModel>();
options = _dbContext.OptionModels.Select(x => x).Where(y => y.PollId == thisPoll.PollId).ToList();
myPoll.options = options;
//List of all UserPollOptions from my UserPollId
List<UserPollOptionModel> myUserPollOptionModels = new List<UserPollOptionModel>();
myUserPollOptionModels =
_dbContext.UserPollOptionModels.Select(x => x).Where(y => y.UserPollId == userPoll.UserPollId).ToList();
myPoll.MyUserPollOptions = myUserPollOptionModels;
//List of all UserPolls, where the user already participated at the survey
List<UserPollModel> userPolls = new List<UserPollModel>();
userPolls = _dbContext.UserPollModels.Select(x => x).Where(y => y.PollId == thisPoll.PollId).Where(z => z.Participation != false).ToList();
//Delete my own UserPollId out of the List
foreach (var userPollModel in userPolls)
{
if (userPollModel.UserPollId == userPoll.UserPollId)
{
userPolls.Remove(userPollModel);
}
}
//Make a list of UserPollOptions for each UserPollRelation that participated
List<List<UserPollOptionModel>> otherUserPollOptionModels = new List<List<UserPollOptionModel>>();
foreach (var userPollModel in userPolls)
{
List<UserPollOptionModel> tempUserPollOptionModels =
_dbContext.UserPollOptionModels.Select(x => x)
.Where(y => y.UserPollId == userPollModel.UserPollId)
.ToList();
otherUserPollOptionModels.Add(tempUserPollOptionModels);
}
myPoll.OtherUserPollOptions = otherUserPollOptionModels;
return myPoll;
}
I also tried it using a false link then the application successfull send a PollParticipation (in line 8) where the attributes had the value Null:
{
poll: null,
options: null,
MyUserPollOptions: null,
OtherUserPollOptions: null
}
I also tried to change the return type to IActionResult or JSON result and tried it with "return new ObjectResult (myPoll)" or "return new JsonResult(myPoll). Another try was to just add only the Poll to the PollParticipation and not the lists. This also did not work.
This is what my PollParticipation class looks like, it is not mapped in the database:
public class PollParticipation
{
public PollModel poll { get; set; }
public List<OptionModel> options { get; set; }
public List<UserPollOptionModel> MyUserPollOptions { get; set; }
public List<List<UserPollOptionModel>> OtherUserPollOptions { get; set; }
}
Can somebody help me? Thank you!
EDIT + Solution
The solution is to write [JsonIgnore] above the virtual lists in the OptionModel and userPollOptionModel class. They were referencing them selfes in the building of the json File.
I have the following types:
public enum Status
{
Online,
Offline
}
public class User
{
private readonly Status _status;
public User(Status status) { _status = status; }
public Status Status {get {return _status; }}
public string Name {get;set;}
}
Now, when executing fixture.CreateMany<User> I want AutoFixture to return two Users, one per status. All other properties - like Name - should be filled with anonymous data.
Question:
How to configure AutoFixture to do this?
I tried the following this:
Register collection that news up the User object:
fixture.Register(
() => Enum.GetValues(typeof(Status)).Cast<Status>().Select(s =>
new User(s)));
The problem with this approach is that AutoFixture doesn't fill the other properties like Name
Customize User to use a factory and register a collection that uses fixture.Create:
f.Customize<User>(c => c.FromFactory((Status s) => new User(s)));
f.Register(() =>
Enum.GetValues(typeof(Status))
.Cast<Status>()
.Select(s => (User)f.Create(new SeededRequest(typeof(User), s),
new SpecimenContext(f))));
That didn't work either. The seed isn't being used.
You could do this:
var users = new Fixture().Create<Generator<User>>();
var onlineUser = users.Where(u => u.Status == Status.Online).First();
var offlineUser = users.Where(u => u.Status == Status.Offline).First();
If you're using AutoFixture.Xunit, the declarative equivalent is:
[Theory, AutoData]
public void CreateOneOfEachDeclaratively(Generator<User> users)
{
var onlineUser = users.Where(u => u.Status == Status.Online).First();
var offlineUser = users.Where(u => u.Status == Status.Offline).First();
// Use onlineUser and offlineUser here...
}
You may declare and use a customization, e.g. StatusGenerator:
var fixture = new Fixture();
fixture.RepeatCount = 2;
fixture.Customizations.Add(new StatusGenerator());
var result = fixture.CreateMany<User>();
A hypothetical implementation of the StatusGenerator could be the following:
internal class StatusGenerator : ISpecimenBuilder
{
private readonly Status[] values;
private int i;
internal StatusGenerator()
{
this.values =
Enum.GetValues(typeof(Status)).Cast<Status>().ToArray();
}
public object Create(object request, ISpecimenContext context)
{
var pi = request as ParameterInfo;
if (pi == null || !pi.ParameterType.IsEnum)
return new NoSpecimen(request);
return this.values[i == this.values.Length - 1 ? i = 0 : ++i];
}
}
Based on Mark's answer, this is what I am using now:
fixture.Customize<User>(c => c.Without(x => x.Status));
fixture.Customize<IEnumerable<User>>(
c =>
c.FromFactory(
() => Enum.GetValues(typeof(Status)).Cast<Status>()
.Select(s => users.First(u => u.Status == s))));
fixture.Create<IEnumerable<User>>(); // returns two Users
I know it is already answered and the Generator was a very interesting finding.
I think there is a much simpler approach for this problem.
var numberOfEnumValues = Enum.GetValues(typeof(Status)).Length;
var users = fixture.CreateMany<User>(numberOfEnumValues);
In case the constructor is more complicated, with multiple Status values, or the model has property setters of Status type. Then you generally have a problem, and the generator might blow as well.
Say that:
public class SuperUser : User
{
public SuperUser(Status status, Status shownStatus): base(status)
{
}
}
Then this will never be evaluated:
var users = fixture.Create<Generator<SuperUser>>();
var offlineUser = users.Where(u => u.Status == Status.Offline).First();
Current way of doing this with AutoFixture 4.17.0
fixture
.Build<User>
.With(u => u.Status, Status.Offline)
.CreateMany(5)
.ToList();