How to change culture class programmatically (Calling implemented Switch) - razor

I have implemented culture in my system. The change with selected combox works fine.
[
[
Now I want depending on User Language to change the language.
I read other descriptions but I can't get it to work.
======================= My switch class Model ===================
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
namespace WorkCollaboration.Models
{
public class SwitchCultureModel
{
public CultureInfo CurrentUICulture { get; set; }
public List<CultureInfo> SupportedCultures { get; set; }
}
}
I have a general logon service where I check user privileges languages....
In the system I created a page were I want to change User language session and so on.
This is how my page looks like
[
========= This is my razor page ==========
#page
#using Microsoft.AspNetCore.Localization
#using Microsoft.AspNetCore.Mvc.Localization
#model WorkCollaboration.Pages.LogonService.LanguageModel
#{
ViewData["Title"] = "UserLanguage";
}
#inject IViewLocalizer Localizer
<h1>#Localizer["Edit"]</h1>
<h4>#Localizer["LogonService"]</h4>
<p>
<a asp-page="/LogonService/IndexLanguage">#Localizer["Back to Index"]</a>
</p>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="LogonService.WorkColUserMail" />
<input type="hidden" asp-for="LogonService.WorkColUserId" class="form-control" />
<input type="hidden" asp-for="LogonService.WorkColUserPassword" class="form-control" />
<input type="hidden" asp-for="LogonService.WorkColUserPasswordConfirm" class="form-control" />
<input type="hidden" asp-for="LogonService.WorkColUserName" class="form-control" />
<input type="hidden" asp-for="LogonService.WorkColUserVerificationMode" class="form-control" />
<input type="hidden" asp-for="LogonService.WorkColEnteredPassword" class="form-control" />
<input type="hidden" asp-for="LogonService.WorkColLoggedIn" class="form-control" />
<div class="form-group">
#Html.LabelFor(model => model.LogonService.WorkColUserLanguage, htmlAttributes: new { #class = "form-group" })
<div class="form-group">
#Html.DropDownListFor(model => model.LogonService.WorkColUserLanguage, new List<SelectListItem>
{
new SelectListItem {Text = "DE", Value = "DE", Selected = true },
new SelectListItem {Text = "EN", Value = "EN" },
}, new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.LogonService.WorkColUserLanguage, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
</div>
<div>
<a asp-page="/LogonService/IndexLanguage">#Localizer["Back to List"]</a>
</div>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
In c# I call the following threds
if (LogonService.WorkColUserLanguage == "DE")
{
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture("de");
Thread.CurrentThread.CurrentUICulture = new
CultureInfo("de");
}
if (LogonService.WorkColUserLanguage == "EN")
{
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture("en");
Thread.CurrentThread.CurrentUICulture = new
CultureInfo("en");
}
However the page language continues on same language
==========Here my c# code ======================
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Microsoft.VisualBasic;
using WorkCollaboration.Data;
using WorkCollaboration.Models;
using System.Collections;
using System.Web;
namespace WorkCollaboration.Pages.LogonService
{
public class LanguageModel : PageModel
{
private readonly WorkCollaboration.Data.WorkCollaborationContext _context;
public LanguageModel(WorkCollaboration.Data.WorkCollaborationContext context)
{
_context = context;
}
[BindProperty]
public Models.LogonService LogonService { get; set; }
public async Task<IActionResult> OnGetAsync(string id)
{
if (id == null)
{
return NotFound();
}
LogonService = await _context.LogonService.FirstOrDefaultAsync(m => m.WorkColUserMail == id);
if (LogonService == null)
{
return NotFound();
}
return Page();
}
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
string id = LogonService.WorkColUserMail;
byte[] ep = LogonService.WorkColEnteredPassword;
string ln = LogonService.WorkColUserLanguage;
string SessionKeyName = "_Name";
string SessionKeyId = "_Id";
string SessionKeyDate = "_Date";
string SessionKeyLang = "_Lang";
if (id == null)
{
return NotFound();
}
//====================================
// Load WorColUser Data with Mail Key
//====================================
LogonService = await _context.LogonService.FirstOrDefaultAsync(m => m.WorkColUserMail == id);
//====================================
// Overwrite Data with GUI Data
//====================================
LogonService.WorkColEnteredPassword = ep;
LogonService.WorkColUserLanguage = ln;
LogonService.WorkColLoggedIn = true;
//====================================
// Create SessionID
//====================================
DateTime now = DateTime.Now;
string valueSystemKeyDates = now.ToString("yyyymmddhh:mm:ss");
HttpContext.Session.SetString(SessionKeyDate, valueSystemKeyDates);
HttpContext.Session.SetString(SessionKeyId, Convert.ToString(LogonService.WorkColUserId));
HttpContext.Session.SetString(SessionKeyName, LogonService.WorkColUserMail);
HttpContext.Session.SetString(SessionKeyLang, LogonService.WorkColUserLanguage);
var SessionIdDate = HttpContext.Session.GetString(SessionKeyDate);
var SessionIdId = HttpContext.Session.GetString(SessionKeyId);
var SessionIdName = HttpContext.Session.GetString(SessionKeyName);
var SessionIdLang = HttpContext.Session.GetString(SessionKeyLang);
LogonService.WorkColUserSessionId = Strings.RTrim(SessionIdDate) + " " + Strings.RTrim(SessionIdName) + " " + Strings.RTrim(SessionIdId) + " " + Strings.RTrim(SessionIdLang);
//=========================================
// Change Culture on specific user language
//=========================================
if (LogonService.WorkColUserLanguage == "DE")
{
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture("de");
Thread.CurrentThread.CurrentUICulture = new
CultureInfo("de");
}
if (LogonService.WorkColUserLanguage == "EN")
{
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture("en");
Thread.CurrentThread.CurrentUICulture = new
CultureInfo("en");
}
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(LogonService).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!LogonServiceExists(LogonService.WorkColUserMail))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("/LogonService/IndexLanguage");
}
private bool LogonServiceExists(string id)
{
return _context.LogonService.Any(e => e.WorkColUserMail == id);
}
}
}
Tks for helping
==============================================================================
Update: 25.1.2021: I investigated further why my culture defined values do not work. And I found the reason why. In my SwithCulturViewComponent.cs The culture is on every page load or exited refreshed to the one defined in the languages in the combo (see Pic 1 or 2)
Now I tried to influence the switch class by setting the culture info from the user language from the session.
=================== SwitchCultureViewComponet ===============
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using WorkCollaboration.Models;
namespace WorkCollaboration.ViewComponents
{
public class SwitchCultureViewComponent : ViewComponent
{
private readonly IOptions<RequestLocalizationOptions> localizationOptions;
public SwitchCultureViewComponent(IOptions<RequestLocalizationOptions> localizationOptions)
{
this.localizationOptions = localizationOptions;
}
public IViewComponentResult Invoke()
{
//=============================================
// Get Session Language
//=============================================
string SessionKeyName = "_Name";
string SessionKeyId = "_Id";
string SessionKeyDate = "_Date";
string SessionKeyLang = "_Lang";
var SessionIdDate = HttpContext.Session.GetString(SessionKeyDate);
var SessionIdId = HttpContext.Session.GetString(SessionKeyId);
var SessionIdName = HttpContext.Session.GetString(SessionKeyName);
var SessionIdLang = HttpContext.Session.GetString(SessionKeyLang);
if (SessionIdId == null)
{
SessionIdId = "0";
}
if (SessionIdId == "")
{
SessionIdId = "0";
}
if (SessionIdLang == null)
{
SessionIdLang = "DE";
}
if (SessionIdLang == "")
{
SessionIdLang = "DE";
}
//=========================================
// Change Culture on specific user language
//=========================================
if (SessionIdLang == "DE")
{
CultureInfo myCIintl = new CultureInfo("de-CH", false);
CultureInfo current = CultureInfo.CurrentCulture;
Console.WriteLine("The current culture is {0}", current.Name);
CultureInfo newCulture;
newCulture = new CultureInfo("de-CH");
CultureInfo.CurrentCulture = newCulture;
Console.WriteLine("The current culture is now {0}",
CultureInfo.CurrentCulture.Name);
CultureInfo.CurrentUICulture = new CultureInfo("de-CH", false);
// CultureInfo.CurrentUICulture = CultureInfo.CreateSpecificCulture("de-CH");
Console.WriteLine("CurrentUICulture is now {0}.", CultureInfo.CurrentUICulture.Name);
}
if (SessionIdLang == "DE")
{
CultureInfo myCIintl = new CultureInfo("en-US", false);
CultureInfo current = CultureInfo.CurrentCulture;
Console.WriteLine("The current culture is {0}", current.Name);
CultureInfo newCulture;
newCulture = new CultureInfo("en-US");
CultureInfo.CurrentCulture = newCulture;
Console.WriteLine("The current culture is now {0}",
CultureInfo.CurrentCulture.Name);
CultureInfo.CurrentUICulture = new CultureInfo("en-US", false);
// CultureInfo.CurrentUICulture = CultureInfo.CreateSpecificCulture("de-CH");
Console.WriteLine("CurrentUICulture is now {0}.", CultureInfo.CurrentUICulture.Name);
}
// How can I influence this code below. I only want this to be executed when I change the UI language code in the dropdown
// Otherwise it should use the custure Info from the above user languages
var cultureFeature = HttpContext.Features.Get<IRequestCultureFeature>();
var model = new SwitchCultureModel
{
SupportedCultures = localizationOptions.Value.SupportedUICultures.ToList(),
CurrentUICulture = cultureFeature.RequestCulture.UICulture
};
return View(model);
}
}
}
How can I influence this code below? I only want this to be executed when I change the UI language code in the dropdown
Otherwise it should use the culture Info from the above user languages
Whenever I try to CurrentUICuture within the "var"...
============ Section in the SwitchViewComponent.cs ==============
var model = new SwitchCultureModel
{
SupportedCultures =
localizationOptions.Value.SupportedUICultures.ToList(),
CurrentUICulture = cultureFeature.RequestCulture.UICulture
};
return View(model);
I get errors. Thank you for your support

Related

How to pass selected checkboxes ID values from view to the controller

I am a newbie to spring boot and thymeleaf,
I have a list of books ina table with checkboxes, I am not sure how to pass selected booksId s from the view to the controller and use them by the borrow or Return bttons? could you please help?
Here is my Html file https://wtools.io/paste-code/b5g4
and this is the relevant part from my bookService implementation :
public void borrowBook(String userEmail, String bookIds, Model model) {
if (!CollectionUtils.isEmpty(books)) {
User user = userRepository.findByEmail(userEmail);
List<String> requestedBooks = getRequestedBookIds(bookIds);
List<Book> borrowedBooks = new ArrayList<>();
List<Book> invalidBooks = new ArrayList<>();
for (Book book : books) {
if (requestedBooks.contains(book.getId()) && !book.isBorrowed() && user != null) {
book.setBorrowed(true);
book.setBorrowedBy(user.getFirstName());
borrowedBooks.add(book);
model.addAttribute("bookStatus", "Book BOrrowed By " + user.getFirstName());
} else {
invalidBooks.add(book);
model.addAttribute("bookStatus", "No Books are available");
}
}
model.addAttribute("inValidBooks", invalidBooks);
model.addAttribute("bookList", borrowedBooks);
}
}
#SuppressWarnings("unchecked")
private List<String> getRequestedBookIds(String bookIds) {
List<String> requestedBookIds = null;
try {
requestedBookIds = new ObjectMapper().readValue(bookIds, ArrayList.class);
} catch (Exception e) {
e.printStackTrace();
}
return !CollectionUtils.isEmpty(requestedBookIds) ? requestedBookIds : new ArrayList<>();
}
and this is from the controller:
#GetMapping(value = "/available", produces = MediaType.APPLICATION_JSON_VALUE)
public String getAvailableFreeBooks(Model model) {
List<Book> availableBooks= bookService.getAllAvailaBooks();
model.addAttribute("listBooks", availableBooks);
return "available_books";
}
In your html you would probably:
<input type="checkbox" th:field="*{requestedBooks}" value="${book.getId}">
omit the id (if you don't need it).
use th:field (instead of name).
set value to the id of the current book.
In your controller: requestedBooks (#ModelAttribute("requestedBooks") List<String> requestedBooks) will (should) contain all checked book ids.
Ref: https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#checkbox-fields
A sample repository:
https://github.com/xerx593/soq67602860
Uppdate:
To process the checkboxes client-sided (jquery),
you can obtain an array of ids like:
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$("#btnBorrow").click(function() {
var reqBookIds = new Array();
$('input[name="requestedBooks"]:checked').each(function() {
reqBookIds .push(this.value);
});
alert("Number of selected Books: "+reqBookIds .length+"\n"+"And, they are: "+reqBookIds);
// do stuff with reqBookIds ...
)};
});
</script>
With the mentioned <input type="checkbox" .../> (consider that <input/> should be inside a <form/>!!) and a button like:
<button id="btnBorrow">Borrow</button>
..the userEmail must come from client side???

Textbox rejecting ##,00 format

I have a MVC project where I am displaying currency amounts in different formats based on the currency of the object.
My project handles the ##.00 format just find, but I have some objects that are using Euros for example that need to be in the ##,00 format instead of ##.00.
Then the page loads in read only mode both formats display correctly, but then the form is edited, it initially shows the currencies correctly, but if I click out of a Euro formatted amount, it drops the "," out of the amount (for example 1000,00 changes to 100000).
In the model, the fields are of DataType = Currency and are decimals. Also, if 1000,00 is tried to save, it is returned as invalid.
How to I get the textbox to handle the both currency formats?
This is my code
#model Projections.Web.ViewModels.Projections.ProjectionFormView
#Html.HiddenFor(model => model.Number)
#Html.HiddenFor(model => model.Department)
#* -- Quarters -- *#
<div class="edit-fields">
<div class="control-group">
#Html.LabelFor(model => model.Q12017, new {#class = "control-label"})
<div class="controls">
#Html.EditorFor(model => model.Q12017)
</div>
</div>
<div class="control-group">
#Html.LabelFor(model => model.Q22017, new {#class = "control-label"})
<div class="controls">
#Html.EditorFor(model => model.Q22017)
</div>
</div>
<div class="control-group">
#Html.LabelFor(model => model.Q32017, new {#class = "control-label"})
<div class="controls">
#Html.EditorFor(model => model.Q32017)
</div>
</div>
<div class="control-group">
#Html.LabelFor(model => model.Q42017, new { #class = "control-label" })
<div class="controls">
#Html.EditorFor(model => model.Q42017)
</div>
</div>
<div class="control-group">
#Html.LabelFor(model => model.Q12018, new { #class = "control-label" })
<div class="controls">
#Html.EditorFor(model => model.Q12018)
</div>
</div>
</div>
Controller:
public ActionResult Edit(string number, string department)
{
// Get the project we're trying to edit a projection for.
var projects = _db.Projects.FindBy(
x => x.Number == number &&
x.PMUsername == SessionWrapper.CurrentManager,
null,
"Projection").ToList();
if (!projects.Any())
{
return Error(
Notices.ProjectNotFoundTitle,
string.Format(Notices.ProjectNotFound, number)
);
}
var project = projects.SingleOrDefault(x => x.Department == department);
var baseProject = projects.SingleOrDefault(x => x.Department == string.Empty);
// Project doesn't exist, error time!
if (project == null || baseProject == null)
{
return Error(
Notices.DepartmentNotFoundTitle,
string.Format(Notices.DepartmentNotFound, department, number)
);
}
project.Projection = project.Projection ?? new Projection { Number = number, Department = department, Project = project };
SetProjectCulture(project.ProjectCurrencyCode);
var projection = Mapper.Map<ProjectionFormView>(project.Projection);
projection.BaseProjectName = baseProject.Name;
return View(projection);
}
private void SetProjectCulture(string currencyCode)
{
var uiHelper = DependencyResolver.Current.GetService<IThreadUIHelper>();
if (!uiHelper.SetUICulture(currencyCode)) return;
var notice = new Notification(string.Format(Notices.ProjectCurrencyNotice, currencyCode));
NotificationHandler.AddNotification(notice);
}
Model
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace Projections.Web.ViewModels.Projections
{
public class Forecast : INotifyPropertyChanged
{
private decimal _q12017;
private decimal _q22017;
private decimal _q32017;
private decimal _q42017;
private decimal _q12018;
[DataType(DataType.Currency)]
public decimal Q12017
{
get { return _q12017; }
set { _q12017 = value; ForecastChanged("Q12017"); }
}
[DataType(DataType.Currency)]
public decimal Q22017
{
get { return _q22017; }
set { _q22017 = value; ForecastChanged("Q22017"); }
}
[DataType(DataType.Currency)]
public decimal Q32017
{
get { return _q32017; }
set { _q32017 = value; ForecastChanged("Q32017"); }
}
[DataType(DataType.Currency)]
public decimal Q42017
{
get { return _q42017; }
set { _q42017 = value; ForecastChanged("Q42017"); }
}
[DataType(DataType.Currency)]
public decimal Q12018
{
get { return _q12018; }
set { _q12018 = value; ForecastChanged("Q12018"); }
}
public decimal Total
{
get
{
var quarters = GetType().GetProperties().Where(x => x.Name.StartsWith("Q")).ToList();
return quarters.Sum(q => (decimal?)q.GetValue(this, null) ?? default(decimal));
}
}
public DateTime? Modified { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void ForecastChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public decimal? this[string name]
{
get
{
var property = GetType().GetProperty(name);
if (property == null) throw new InvalidOperationException("Invalid property specified.");
if (property.PropertyType == typeof(decimal))
{
return property.GetValue(this, null) as decimal?;
}
throw new InvalidOperationException("Invalid property specified.");
}
}
}
}
The default model binder will only handle decimals with a U.S.-style decimal point (.). If you need to accept a comma, you need a custom model binder. I use the following, which I found original here.
public class DecimalModelBinder : IModelBinder {
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext) {
ValueProviderResult valueResult = bindingContext.ValueProvider
.GetValue(bindingContext.ModelName);
ModelState modelState = new ModelState { Value = valueResult };
object actualValue = null;
try {
actualValue = Convert.ToDecimal(valueResult.AttemptedValue,
CultureInfo.CurrentCulture);
}
catch (FormatException e) {
modelState.Errors.Add(e);
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return actualValue;
}
}
Then, register it in Application_Start in Global.asax:
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
You may need to alter the model binder to your specific usage scenario. This version simply converts based on the current culture, but you may need to do some different type of processing here if you're going to be handling both periods and commas as "decimal points".

MVC view code for bool type input

In one of my first MVC projects I encountered the following part of code in my "Create" view.
<div class="form-group">
#Html.LabelFor(model => model.Attend, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="checkbox">
#Html.EditorFor(model => model.Attend)
#Html.ValidationMessageFor(model => model.Attend, "", new { #class = "text-danger" })
</div>
</div>
</div>
This was scaffolded based on the following property in my model:
public virtual bool? Attend { get; set; }
What this will show for me on the "Create" view is a dropdown with the following values: Not Set; True; False;
Is there a way I can change these values in the dropdownlist for my bool so that it says something more readable/understandable for a user like: Yes; No;?
I tried to search for a solution and I think it has something to do with the following line:
#Html.EditorFor(model => model.Attend)
As #Stephen Muecke said you can create your own selectlist. You can do it with your own editor template .
Here is how i have done it:
Create EditorTeplates folder in Views/Shared
Create YesNoNotSelected.cshtml in this folder with this code:
#model bool?
#Html.DropDownList("", new SelectListItem[]
{
new SelectListItem()
{
Text = "Not set",
Value = String.Empty,
Selected = !Model.HasValue
},
new SelectListItem()
{
Text = "True",
Value = "true",
Selected = Model.HasValue && Model.Value
},
new SelectListItem()
{
Text = "False",
Value = "false",
Selected = Model.HasValue && !Model.Value
}
})
In your model add UIHintAttribute above Attend property like this:
[UIHint("YesNoNotSelected")]
public virtual bool? Attend { get; set; }
Now EditorFor helper should render your property according to this template.
I like the best of all worlds scenario:
I don't want to always require a UIHint
I don't want to use UIHint at all, it's not descriptive
I want bools to be extensible; yes/no, true/false, etc
Here is how I implemented it:
/Models/BooleanType.cs
public enum BooleanDisplay
{
undefined = 0,
YesNo = 1,
TrueFalse = 2,
GoodEvil = 3
}
/MVC/UIBooleanType.cs
[AttributeUsage(AttributeTargets.Property)]
public class UIBooleanAttribute : UIHintAttribute
:base("boolean", "MVC")
{
public UIBoolean(BooleanType displayAs)
{
DisplayAs = displayAs;
}
public BooleanDisplay DisplayAs { get; set; }
}
/Views/Shared/EditorTemplates/boolean.cshtml
#model boolean?
#{
// default
var displayAs = BooleanDisplay.TrueFalse;
var uiBoolean = ViewData
.ModelMetadata
.ContainerType
.GetProperty(ViewData.ModelMetadata.PropertyName)
.GetCustomAttributes(typeof(UIBooleanAttribute))
.Select(ca => ca as UIBooleanAttribute)
.FirstOrDefault(ca => ca != null);
if (uiBoolean != null)
{
displayAs = uiBoolean.DisplayAs;
}
var values = new List<SelectListItem>()
{
new SelectListItem()
{
Text = "Not set",
Value = String.Empty,
Selected = !Model.HasValue
}
};
switch(displayAs)
{
default:
throw new NotImplementedException(displayAs.ToString()
+ " is not implemented in boolean.cshtml";
YesNo:
values.Add(new SelectListItem()
{
Text = "Yes",
Value = "true",
Selected = Model.HasValue && Model.Value
});
values.Add(new SelectListItem()
{
Text = "No",
Value = "false",
Selected = Model.HasValue && !Model.Value
});
TrueFalse:
// etc
}
}
#Html.DropDownList("", values)
usage:
ViewModel:
public class Person
{
// defaults to True/False
public bool AreYouHappy { get; set; }
[UIBoolean(BooleanDisplay.GoodEvil)]
public bool IsInherently { get; set; }
}
View:
#model Person
#Html.EditorFor(p => p.AreYouHappy)
#Html.EditorFor(p => p.IsInherently)

Razor webgrid get selected row data

In my Razor view, I have this webgrid:
#{
var grid = new WebGrid(Model, canPage: false, selectionFieldName: "VendorClassID", canSort:false);
}
#grid.GetHtml(
headerStyle: "header",
htmlAttributes: new{id = "tableGrid"},
tableStyle: "webgrid",
selectedRowStyle: "webgrid-selected-row",
columns: grid.Columns(
grid.Column(header: "Select", format: #<text>#item.GetSelectLink("Select")</text>),
grid.Column("ClassID", "ID"),
grid.Column("ClassNum", "Class Num"),
grid.Column("Description")
)
)
#if (grid.HasSelection)
{
var x = #grid.SelectedRow;
}
It's my understanding that when I click the generated "select" link, the page posts back and the URL gets a parameter "VendorClassID = selectrowindex" added on. However, the value of the parameter seems to be the index of the selected row, which isn't particularly useful to me. Is there anyway to have the parameter value be set to a value from the selected row (ClassID, etc)? The #grid.SelectedRow doesn't seem to know anything about the row's data either, but I am new to MVC so perhaps there is a way to get the row data from there?
I found the solution, I got the data I wanted (VendorClassID), by using
#if (grid.HasSelection)
{
var x = grid.SelectedRow.Value.VendorClassID;
//logic
}
VendorClassID is an attribute of my VendorClass. The page has a list of VendorClasses for its Model
Model:
public class SchemeDetailsModel
{
[Display(Name = "File Name")]
public string FileName { get; set; }
public Int64 FileId { get; set; }
[DataType(DataType.Date)]
public DateTime Date { get; set; }
[Display(Name = "Scheme Id")]
public int SchemeId { get; set; }
public string Status { get; set; }
[Display(Name="Validation Error Report")]
public string ValidationErrorReport { get; set; }
}
Controller:
[HttpGet]
public ActionResult History()
{
if (ModelState.IsValid)
{
List<SchemeDetailsModel> objSchemeDetails = new List<SchemeDetailsModel>();
string employerId = Session["EmployerId"].ToString();
objSchemeDetails = _repository.getSchemeDetails(employerId);
return View(objSchemeDetails);
}
return View();
}
Repository:
public List<SchemeDetailsModel> getSchemeDetails(string employerId)
{
List<SchemeDetailsModel> objDetails = new List<SchemeDetailsModel>();
var query = (from efd in _context.EmployerFileDatas
//where efd.EmployerId == employerId
orderby efd.FileName
select new
{
efd.FileName,
efd.Timestamp,
//efhd.SchemeId,
efd.ValidationStatus
}).ToList();
//join efhd in _dataContext.EmployerFileHeaderDetails on efd.EmployerId equals efhd.EmployerId
if(query!=null)
{
foreach (var item in query)
{
objDetails.Add(new SchemeDetailsModel { FileName = item.FileName, Date = item.Timestamp, Status = item.ValidationStatus, ValidationErrorReport = "View" });
}
return objDetails;
}
View:
#model IEnumerable<EFITestHarness.Models.SchemeDetailsModel>
#using System.Web.Helpers;
#{
ViewBag.Title = "SchemeDetails";
Layout = "~/Views/Shared/_Layout.cshtml";
var grid = new WebGrid(Model, canPage: true, rowsPerPage: 4, selectionFieldName: "selectedRow"); grid.Pager(WebGridPagerModes.NextPrevious);
}
<table>
<tr>
<td>#Html.ActionLink("Back", "FileUpload", "Home", null, new { #class = "form-control" })
</td>
</tr>
</table>
<div id="gridContent" class="webGridWrapper">
#grid.GetHtml(tableStyle: "webGrid",
footerStyle: "foot",
headerStyle: "webGridHeader",
alternatingRowStyle: "webGridAlt",
selectedRowStyle: "select",
columns: grid.Columns(
grid.Column("FileName"), //the model fields to display
grid.Column("Date"),
grid.Column("SchemeId"),
grid.Column("Status"),
grid.Column("ValidationErrorReport", format: (item => Html.ActionLink((string)(#item.ValidationErrorReport).ToString(), "ValidationResults", new { fileName = #item.FileName })))
))
</div>
Controller:
[HttpGet]
public ActionResult ValidationResults(string fileName)
{
Session["FileName"] = fileName;
if (ModelState.IsValid)
{
List<ValidationResultsModel> objValidationResults = new List<ValidationResultsModel>();
string employerId = Session["EmployerId"].ToString();
objValidationResults = _repository.getValidationResultsDetails(101);
if (objValidationResults.Count() > 0)
{
//var dataGrid = new GridView();
Session["results"] = objValidationResults;
//dataGrid.DataSource = objValidationResults;
//dataGrid.DataBind();
return View(objValidationResults);
}
else
return PartialView("~/Views/Results.cshtml");
}
return View();
}
Model:
public class ValidationResultsModel
{
public string NINO { get; set; }
public DateTime? DOB { get;set;}
public string Transaction { get;set; }
public string Element { get;set; }
public string ErrorMessage { get; set; }
}
View:
#model IEnumerable<EFITestHarness.Models.ValidationResultsModel>
#using System.Web.Helpers;
#{
ViewBag.Title = "ValidationResults";
Layout = "~/Views/Shared/_Layout.cshtml";
var grid = new WebGrid(Model, canPage: true, rowsPerPage:2, selectionFieldName: "selectedRow"); grid.Pager(WebGridPagerModes.NextPrevious);
}
#using (Html.BeginForm("ValidationResults", "Home", new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<table>
<tr>
<td>#Html.ActionLink("Back", "History", "Home", null, new { #class = "form-control" })
</td>
</tr>
</table>
<div class="container-fluid" style="font-size:medium;color:blue;">
Validation Results: </div>
<div style="font-size:medium;color:black;">1.Error Message<br />
</div>
<div id="gridContent" class="webGridWrapper">
#grid.GetHtml(tableStyle: "webGrid",
footerStyle: "foot",
headerStyle: "webGridHeader",
alternatingRowStyle: "webGridAlt",
selectedRowStyle: "select",
columns: grid.Columns(
grid.Column("NINO"), //the model fields to display
grid.Column("DOB"),
grid.Column("Transaction"),
grid.Column("Element"),
grid.Column("ErrorMessage", style: "description")
))
</div>
}
<div style="font-size:medium;color:black;">
Select the Button below to Download the Validation error Report
</div>
<div>
<input type="button" class="btn btn-primary btn-md" value="Download" onclick="#("window.location.href='" + #Url.Action("Download", "Home") + "'");" />
</div>
Controller:
[HttpGet]
public ActionResult Download()
{
var dataGrid = new GridView();
dataGrid.DataSource = Session["results"];
dataGrid.DataBind();
/*Code to eport the detail in excel sheet format*/
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename='" + Session["FileName"] + "'.xls");
Response.ContentType = "application/ms-excel";
Response.Charset = "";
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
dataGrid.RenderControl(htw);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
return View();
}
partial view:
#{
ViewBag.Title = "ValidationResults";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<table>
<tr>
<td>
#Html.ActionLink("Back", "History", "Home", null, new { #class = "form-control" })
</td>
</tr>
</table>
<div class="container-fluid" style="font-size:medium;color:blue;">
Validation Results:
</div>
<div style="font-size:medium;color:black;">
1.Successful Message<br />
</div>
}

Localized ViewEngines using multiple routes

I am trying to make a simple multi-language website. Overriding FindView to get the file based on the language is easy, my problem comes in the routing part.
I would like to do is: (have a website with 2 languages - pt-br and en-us, let abbreviate to onlu pt and en - the default would be PT)
User types www.mysite.com -> would find the languages in the user header request and if the user doesn´t have any of them, he would be redirected to the default PT, so the end result would be www.mysite.com in Portuguese. If he has en, he would be redirected to www.mysite.com/en/ , the result would be the view in English.
If the user types www.mysite.com/pt/ -> I would check that he wants the default and would redirect to www.mysite.com in Portuguese.
I did a custom engine to get the correct view based on the language. But it´s not working 100% because the routing problem.
IN my case I am trying to route with
routes.MapRoute(
"Localization", // Route name
"{lang}/{controller}/{action}", // URL with parameters
new { lang = "pt", controller = "Home", action = "Index" } //defaults
);
But with this, when someone types /pt/ will not redirect to the root of the site.
Another problem with the route is that I don´t want to anyone typing the controller name, I just want the action, my website just have one Home controller with few actions.
Another problem is the that I want a different action name, like, CONTACT in English and CONTATO in Portuguese, they should appear on the address bar like www.mysite.com/Contato or www.mysite.com/en/Contact
Mu Engine I did base on this solution http://www.counity.at/blog/2012/asp-net-mvc3-localization-using-culture-dependent-views/ by Guido Breitenhuber
Here is the code with some tweaks (it´s not working 100% yet)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Globalization;
namespace Ala.MultiLanguage
{
public class LocalizedViewLocation : RazorViewEngine
{
private static readonly string[] _emptyLocations = new string[0];
public string[] LocalizedViewLocationFormats { get; set; }
public string[] LocalizedMasterLocationFormats { get; set; }
protected string[] LocalizedPartialViewLocationFormats { get; set; }
public LocalizedViewLocation()
{
// Define the localized view locations
// 0: Language
// 1: View name
// 2: Controller name
LocalizedViewLocationFormats = new[] {
"~/Views/{0}/{2}/{1}.cshtml",
"~/Views/Shared/{0}/{1}.cshtml"};
MasterLocationFormats = new[] {
"~/Views/{0}/{2}/{1}.cshtml",
"~/Views/Shared/{0}/{1}.cshtml"};
LocalizedPartialViewLocationFormats = new[] {
"~/Views/{0}/{2}/{1}.cshtml",
"~/Views/Shared/{0}/{1}.cshtml"};
}
public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (String.IsNullOrEmpty(partialViewName))
throw new ArgumentException("Parameter partialViewName is null or empty.", "partialViewName");
string[] searched;
var controllerName = controllerContext.RouteData.GetRequiredString("controller");
var partialPath = GetPath(controllerContext, LocalizedPartialViewLocationFormats, partialViewName, controllerName, out searched);
if (String.IsNullOrEmpty(partialPath))
{
var baseRes = base.FindPartialView(controllerContext, partialViewName, useCache);
if (baseRes.View != null)
return baseRes;
return new ViewEngineResult(searched.Union(baseRes.SearchedLocations));
}
return new ViewEngineResult(CreatePartialView(controllerContext, partialPath), this);
}
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (String.IsNullOrEmpty(viewName))
throw new ArgumentException("Parameter viewName is null or empty.", "viewName");
string[] viewLocationsSearched;
string[] masterLocationsSearched;
var controllerName = controllerContext.RouteData.GetRequiredString("controller");
var viewPath = GetPath(controllerContext, LocalizedViewLocationFormats, viewName, controllerName, out viewLocationsSearched);
var masterPath = GetPath(controllerContext, LocalizedMasterLocationFormats, masterName, controllerName, out masterLocationsSearched);
if (String.IsNullOrEmpty(viewPath) || (String.IsNullOrEmpty(masterPath) && !String.IsNullOrEmpty(masterName)))
{
var baseRes = base.FindView(controllerContext, viewName, masterName, useCache);
if (baseRes.View != null)
return baseRes;
return new ViewEngineResult(viewLocationsSearched.Union(masterLocationsSearched).Union(baseRes.SearchedLocations));
}
return new ViewEngineResult(CreateView(controllerContext, viewPath, masterPath), this);
}
private string GetPath(ControllerContext controllerContext, string[] locations, string name, string controllerName, out string[] searchedLocations)
{
searchedLocations = _emptyLocations;
if (String.IsNullOrEmpty(name))
return String.Empty;
if (IsSpecificPath(name))
return String.Empty;
return GetPathFromGeneralName(controllerContext, locations, name, controllerName, ref searchedLocations);
}
private static bool IsSpecificPath(string name)
{
char c = name[0];
return (c == '~' || c == '/');
}
private string GetPathFromGeneralName(ControllerContext controllerContext, string[] locations, string name, string controllerName, ref string[] searchedLocations)
{
var result = String.Empty;
searchedLocations = new string[locations.Length];
for (int i = 0; i < locations.Length; i++)
{
var location = locations[i];
var virtualPath = string.Format(CultureInfo.InvariantCulture, location, CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, name, controllerName);
if (FileExists(controllerContext, virtualPath))
{
searchedLocations = _emptyLocations;
result = virtualPath;
break;
}
searchedLocations[i] = virtualPath;
}
return result;
}
}
}
Well, after some timing trying to do in the best way, I ´ve found one solution much easier and fast to implement.
Just mapped the routes that I want one-by-one in the global.asax. This will work and will be fast to implement if you have only few pages and languages.
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("Default-BR", "", new { controller = "Home", action = "Index" });
routes.MapRoute("Default-EN", "en", new { controller = "Home", action = "IndexEN" });
routes.MapRoute("HotelBR", "Hotel", new { controller = "Home", action = "Index" });
routes.MapRoute("HotelEN", "en/Hotel", new { controller = "Home", action = "IndexEN" });
routes.MapRoute("Apartamento", "Apartamento", new { controller = "Home", action = "Apartamentos" });
routes.MapRoute("Apartamentos", "Apartamentos", new { controller = "Home", action = "Apartamentos" });
routes.MapRoute("Apartments", "en/Apartments", new { controller = "Home", action = "ApartamentosEN" });
routes.MapRoute("Localizacao", "Localizacao", new { controller = "Home", action = "Localizacao" });
routes.MapRoute("Location", "en/Location", new { controller = "Home", action = "LocalizacaoEN" });
routes.MapRoute("Tarifa", "Tarifa", new { controller = "Home", action = "Tarifas" });
routes.MapRoute("Tarifas", "Tarifas", new { controller = "Home", action = "Tarifas" });
routes.MapRoute("Rates", "en/Rates", new { controller = "Home", action = "TarifasEN" });
routes.MapRoute("Reserva", "Reserva", new { controller = "Home", action = "Reservas" });
routes.MapRoute("Reservas", "Reservas", new { controller = "Home", action = "Reservas" });
routes.MapRoute("Booking", "en/Booking", new { controller = "Home", action = "ReservasEN" });
routes.MapRoute("Contato", "Contato", new { controller = "Home", action = "Contato" });
routes.MapRoute("Contact", "en/Contact", new { controller = "Home", action = "ContatoEN" });