ASP.NET Core MVC & C# - redirect to same view ( action ) when changing language using culture - razor

I have localization in my project. What I want is to whenever a user changes language it redirects him to the same page he was in. But now I always redirect him to the Index page.
View (layout) :
<a asp-controller="language" asp-action="change" asp-route-culture="en-GB" class="btn btn-clear primary"›
<i class="fas fa-globe-americas mx-1" title="Arabic"></i>#sharedResource["arabic"]
</a›
‹a asp-controller="language" asp-action="change" asp-route-culture="en-US" class="btn btn-clear-primary"›
<i class-"fas fa-globe-americas mx-1" title="English"›</i>English
</a›
Controller (languageController):
public IActionResult Change( string culture)
{
Response.Cookies.Append (CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(newRequestCulture(culture)),
new CookieOptions ( Expires = DateTimeOffset.UtcNow.AddMonths(1)}
):
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(culture);
Thread.CurrentThread.CurrentUICulture=CultureInfo.CreateSpecificCulture(culture);
//But independent of language, keep datetime format same
DateTimeFormatInfo englishDateTimeFormat = new CultureInfo("en-CA").DateTimeFormat;
Thread.CurrentThread.CurrentCulture.DateTimeFormat=englishDateTimeFormat;
return RedirectToAction("Index", "Home");
}
How can I redirect the user to the same page that he changes the language inside it?

I do this and it works for me.
public IActionResult Change(string culture)
{
Response.Cookies.Append (CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(newRequestCulture(culture)),
new CookieOptions ( Expires = DateTimeOffset.UtcNow.AddMonths(1)}
);
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(culture);
Thread.CurrentThread.CurrentUICulture=CultureInfo.CreateSpecificCulture(culture);
//But independent of language, keep datetime format same
DateTimeFormatInfo englishDateTimeFormat = new CultureInfo("en-CA").DateTimeFormat;
Thread.CurrentThread.CurrentCulture.DateTimeFormat=englishDateTimeFormat;
string referer = Request.Headers["Referer"].ToString();
string action = referer.Substring(referer.LastIndexOf("/")+1,referer.Length-referer.LastIndexOf("/")-1);
string afterRemoveAction = referer.Substring(0, referer.LastIndexof("/") );
string controller = afterRemoveAction.Substring(afterRemoveAction.LastIndexOf("/")+1,
afterRemoveAction.Length-afterRemoveAction.LastIndexOf("/")- 1);
return RedirectToAction(action, controller);
}

Related

Laravel: How to insert data on click on href link using route and controller

After Click On "Yes I am Sure" button data not inserting into database
Here Is my code Auth user block another user from viewing their profile.
so, i am inserting data auth username and block user username into data after click on "Yes I am Sure" but data is not inserted.
my .blade file profile/index.blade.php
here "Yes I am Sure" href link to go on route
<div class="cd-popup" role="alert">
<div class="cd-popup-container"><br>
<div class="content_block">Are you sure you want to block this person?</div><br>
<div class="content_block_instruct">Hide content and notifications from this user.</div><br>
<ul class="cd-buttons">
<li> Yes I am Sure!</li>
<li>Cancled</li>
</ul>
Close
</div> <!-- cd-popup-container -->
</div>
Route File
Route::post('/{username}', [
'uses' => 'Profile\UserProfileController#blockUser',
'as' => 'profile.index',
]);
Controller file
Whose username show on URL, with their username check BlockUser model if block_username and URL username same data not inserted else data not same their data inserted into database
public function blockUser(Request $request, $username)
{
$blocked = User::where('id', Auth::user()->id)->first();
if (blockuser::where('block_username', $username)->first()){
}else{
$blocked = new blockuser;
$blocked->user_username = Auth::user()->username;
$blocked->block_username = $username;
$blocked->save();
}
$user = Auth::user();
$userprofile = userprofile::where('user_id', Auth::user()->id)->first();
return view('profile.index',compact('user', 'userprofile'));
}
Here is my User Model
public function blockuser(){
return $this->hasOne( BlockUser::class);
}
BlockUser Model
use App\User;
class BlockUser extends Authenticatable
{
public $timestamps = false;
protected $fillable = [
'user_username', 'block_username',
];
public function user()
{
return $this->belongsTo( User::class, 'username' );
}
}
Database table block_users
id user_username block_username
1
2
Clicking simply on link actually makes GET HTTP Request. You need to change fromRoute::post(...) to Route::get(...). If you still want to have post method, then make simple ajax call with post method on onclick event of the anchor tag.

NetSuite's SuiteCommerce Advance: Customize Multi Language With Single Domain(Without Hosts)?

In SuiteCommerce Advance Vision release by default behavior to setup multi language is to add multiple domain under Setup-->Configuration-->Multi Domain Tab--> Hosts
Once you setup this you can able to see drop down in your web store which will have domain and language associate with that domain. We have already implemented this feature.
But, SCA also has feature to setup multi language with 'lang' parameter which will automatically change language withing single domain like below
We did this already-->(With multiple domain)
https://www.en.scasite.com/
https://www.fr.scasite.com/
We want below setup-->
https://www.scasite.com/?lang=en_US
https://www.scasite.com/?lang=fr_FR
So, Can any one have idea how we can pass language param in url?
Yes you are right SCA out of the box don't have this feature, but yes you can send 'lang' param in url and can able to change your language.
Remember if you are uding SCA vision release, do not add any language hosts in configuration under setup tab
To pass 'lang' param i.e www.domain.com/lang=it_IT etc
Override the Host selector file in your custom module to do this, you need to create below two files under global view
1.Modules/custom/GlobalViews#1.0.0/JavaScript/GlobalViews.HostSelector.View.js
Copy & paste below code in setLanguage: function (e){}
, setLanguage: function (e)
{
var language_code = jQuery(e.target).val()
, selected_language = _.find(SC.ENVIRONMENT.availableLanguages, function (language)
{
return language.locale === language_code;
});
// We use the param **"cur"** to pass this to the ssp environment
var current_search = Utils.parseUrlOptions(window.location.search);
// if we are in a facet result we will remove all facets and navigate to the default search
// TODO REVIEW THIS
if (window.location.hash !== '' && _.values(SC._applications)[0].getLayout().currentView instanceof BrowseView)
{
window.location.hash = Configuration.defaultSearchUrl || '';
}
current_search.lang = selected_language.locale;
window.location.search = _.reduce(current_search, function (memo, val, name)
{
return val ? memo + name + '=' + val + '&' : memo;
}, '?');
}
Use below code in getContext() to return some data to handlbar view
var available_languages = _.map(SC.ENVIRONMENT.availableLanguages, function(language)
{
// #class GlobalViews.CurrencySelector.View.Context.Currency
return {
// #property {String} code
code: language.locale
// #property {String} internalId
, internalId: language.internalid
// #property {String} isDefault
, isDefault: language.isdefault
// #property {String} symbol
, symbol: language.languagename
// #property {String} displayName
, displayName: language.locale|| language.locale
, isSelected: SC.ENVIRONMENT.currentLanguage.locale === language.locale
};
});
// #class GlobalViews.CurrencySelector.View.Context
return {
// #property {Boolean} showCurrencySelector
showLanguageSelector: !!(SC.ENVIRONMENT.availableLanguages && SC.ENVIRONMENT.availableLanguages.length > 1)
// #property {Array<GlobalViews.CurrencySelector.View.Context.Currency>} availableCurrencies
, availableLanguages: available_languages || []
// #property {String} currentCurrencyCode
// #property {String} currentCurrencySymbol
, currentLanguageSymbol: SC.getSessionInfo('language').languagename
};
}
Copy & Paste Below code in below file
Modules/custom/GlobalViews#1.0.0/Templates/global_views_host_selector.tpl
{{#if showLanguageSelector}}
<div class="global-views-currency-selector">
<span class="global-views-host-selector-addon">
{{currentLanguageSymbol}}
</span>
<select data-toggle="currency-selector" class="global-views-currency-selector-select">
{{#each availableLanguages}}
<option value="{{code}}" {{#if isSelected}}selected{{/if}}>
{{symbol}}
</option>
{{/each}}
</select>
</div>
{{/if}}
Done!! Now you can see 'lang' param is being added into url
Let me know if you want more help on this.

Submit AngularJS form with CodeIgniter

Let me preface this by saying I'm new to AngularJS & CodeIgniter.
Trying to create a single page app. In the center it displays news stories. On the side is a form to submit new stories. I'm to the point where the stories display fine from the DB. But when I try to create new stories from the form on the side, it enters 0 into the DB. I assume I have an issue with my function in the model. And it's probably as basic as not having the information encoded correctly to pass between MVC.
index.php
<div class="span2" ng-controller="NewStoryCtrl">
<h4>New Story</h4>
<form name="newStory">
<label for="title">Title: </label>
<input type="text" name ="title" ng-model="news.title" required>
<label for="text">Text: </label>
<textarea type="text" name="text" ng-model="news.text"required></textarea>
<button ng-click="createNews()">Submit</button>
</form>
controller.js
function NewStoryCtrl($scope, $http) {
$scope.news = {title:$scope.title, text:$scope.text};
$scope.createNews = function(){
$http.post('/ci/index.php/news/create/',$scope.news);
};}
news.php (controller)
public function create() {
$this->news_model->set_news();
}
news_model.php (model)
public function set_news() {
$this->load->helper('url');
$slug = url_title($this->input->post('title'), 'dash', TRUE);
$data = array(
'title' => $this->input->post('title'),
'slug' => $slug,
'time' => time(),
'text' => $this->input->post('text')
);
return $this->db->insert('news', $data);
}
The stuff in the model is leftover from my initial CI news tutorial. That's why I assume the error is here.
What's the best way to pass the information from the controllers.js to the model?
As expected, my issue was with not getting the right type of data. Controller was expecting a variable, but in Angular controller I was passing it as JSON. I hadn't ever gone through decoding.
news.php (controller)
public function create() {
$data = json_decode(file_get_contents('php://input'), TRUE);
$this->news_model->set_news($data);
}
And then in the model, I just needed to pass it as a parameter to set_news(). I ended up changing some variable names, just for personal clarification.
*news_model.php*
public function set_news($data) {
$this->load->helper('url');
$slug = url_title($data['title'], 'dash', TRUE);
$retval = array(
'title' => $data['title'],
'slug' => $slug,
'time' => time(),
'text' => $data['text']
);
return $this->db->insert('news', $retval);
}
I haven't used Angular.js, but your data format is probably correct. For example, Backbone sends a single $_POST variable called model with json encoded data, as I have used it.
It is imperative that you use Firebug, Webdev or other tools to see what is going on when you try to do AJAX work like this; otherwise you will go crazy . Look at the variable being sent to your backend - it is probably described, an encoded single var you will need to collect, json_decode, CLEAN & VALIDATE and then use.

ASP.Net MVC SelectList not 'Selecting' Correct Item

I have been asked to look at a bug in some ASP.Net MVC code and have a (to me) very odd problem with a SelectList.
The code from the controller to generate the items (a method to return a SelectList, there are 5 in total). Each SelectList is then saved into the ViewData collection.
List<SelectListItem> items = new List<SelectListItem>();
string yesText = "Yes";
string noText = "No";
if (ci.LCID.Equals((int)LanguageCodes.FRANCE))
{
yesText = "Oui";
noText = "Non";
}
SelectListItem yesItem = new SelectListItem();
yesItem.Text = yesText;
yesItem.Value = ((int)MarketingBy.Yes).ToString();
yesItem.Selected = selectedValue != null && selectedValue.Equals(int.Parse(yesItem.Value));
SelectListItem noItem = new SelectListItem();
noItem.Text = noText;
noItem.Value = ((int)MarketingBy.No).ToString();
noItem.Selected = selectedValue != null && selectedValue.Equals(int.Parse(noItem.Value));
items.Add(yesItem);
items.Add(noItem);
return new SelectList(items, "Value", "Text", yesItem.Selected ? yesItem.Value : noItem.Value);
A quick 'quickwatch' at the point of creation suggests everything is ok:
At the point the view is being rendered, the values still look ok. However when the view loads, the first item in the list is always selected. The HTML generated is:
<tr>
<td>Fax</td>
<td>
<select id="MarketingByFax" name="MarketingByFax">
<option value="134300002">Yes</option>
<option value="134300001">No</option>
</select>
</td>
</tr>
(Other values ommitted for clarity).
Any ideas? Or avenues to research? The author is adamant that this was working 'up til last week' (I have no idea either way).
Edit: Code for the view -
<td><%: Html.DropDownList("MarketingByFax", (SelectList)ViewData["MarketingByFaxList"])%></td>
This code looks just horrible in every imaginable aspect (IMHO of course). I have no idea why it doesn't work and I don't want to know. All I can do is to suggest you how to improve it (so you can stop reading this post if you are looking for a solution about why your code doesn't work as I have no freaking idea).
So the first improvement would be to get rid of any ViewData and introduce a view model:
public class MyViewModel
{
public string SelectedValue { get; set; }
public IEnumerable<SelectListItem> Items { get; set; }
}
then I would have a controller action that would populate this view model:
public ActionResult Index()
{
var model = new MyViewModel
{
// I want to preselect the second value
SelectedValue = "No",
Items = new[]
{
new SelectListItem { Value = "Yes", Text = "yeap !" },
new SelectListItem { Value = "No", Text = "nope !" },
}
};
return View(model);
}
and in my strongly typed view I would simply bind the helper to the view model:
<%= Html.DropDownListFor(
x => x.SelectedValue,
new SelectList(Model.Items, "Value", "Text")
) %>
Also if you want to work with some enum types you may find the following extension method useful.
See how easy it is? No more ugly casts with ViewData, no more need to define any lists and specify some complicated conditions, ...
Remark: once again, those are just my 2¢, you can continue the combat with ViewData if you will.
you can try
<%: Html.DropDownList("MarketingByFax", (IEnumerable<SelectListItem>)ViewData["MarketingByFaxList"])%>
dropdwon has an overload that accepts the enumeration of Selectlist type objects and it sets the value of list automatically depending upon Selected property of selectListItems in the list. for this you have to set
ViewData["MarketingByFaxList"] = items;//where item is IEnumerable<SelectListItem> or List<SelectListItem> as you used in your code

How do I get the collection of Model State Errors in ASP.NET MVC?

How do I get the collection of errors in a view?
I don't want to use the Html Helper Validation Summary or Validation Message. Instead I want to check for errors and if any display them in specific format. Also on the input controls I want to check for a specific property error and add a class to the input.
P.S. I'm using the Spark View Engine but the idea should be the same.
So I figured I could do something like...
<if condition="${ModelState.Errors.Count > 0}">
DisplayErrorSummary()
</if>
....and also...
<input type="text" value="${Model.Name}"
class="?{ModelState.Errors["Name"] != string.empty} error" />
....
Or something like that.
UPDATE
My final solution looked like this:
<input type="text" value="${ViewData.Model.Name}"
class="text error?{!ViewData.ModelState.IsValid &&
ViewData.ModelState["Name"].Errors.Count() > 0}"
id="Name" name="Name" />
This only adds the error css class if this property has an error.
<% ViewData.ModelState.IsValid %>
or
<% ViewData.ModelState.Values.Any(x => x.Errors.Count >= 1) %>
and for a specific property...
<% ViewData.ModelState["Property"].Errors %> // Note this returns a collection
To just get the errors from the ModelState, use this Linq:
var modelStateErrors = this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors);
Condensed version of #ChrisMcKenzie's answer:
var modelStateErrors = this.ModelState.Values.SelectMany(m => m.Errors);
This will give you one string with all the errors with comma separating
string validationErrors = string.Join(",",
ModelState.Values.Where(E => E.Errors.Count > 0)
.SelectMany(E => E.Errors)
.Select(E => E.ErrorMessage)
.ToArray());
Putting together several answers from above, this is what I ended up using:
var validationErrors = ModelState.Values.Where(E => E.Errors.Count > 0)
.SelectMany(E => E.Errors)
.Select(E => E.ErrorMessage)
.ToList();
validationErrors ends up being a List<string> that contains each error message. From there, it's easy to do what you want with that list.
Thanks Chad! To show all the errors associated with the key, here's what I came up with. For some reason the base Html.ValidationMessage helper only shows the first error associated with the key.
<%= Html.ShowAllErrors(mykey) %>
HtmlHelper:
public static String ShowAllErrors(this HtmlHelper helper, String key) {
StringBuilder sb = new StringBuilder();
if (helper.ViewData.ModelState[key] != null) {
foreach (var e in helper.ViewData.ModelState[key].Errors) {
TagBuilder div = new TagBuilder("div");
div.MergeAttribute("class", "field-validation-error");
div.SetInnerText(e.ErrorMessage);
sb.Append(div.ToString());
}
}
return sb.ToString();
}
Here is the VB.
Dim validationErrors As String = String.Join(",", ModelState.Values.Where(Function(E) E.Errors.Count > 0).SelectMany(Function(E) E.Errors).[Select](Function(E) E.ErrorMessage).ToArray())
If you don't know what property caused the error, you can, using reflection, loop over all properties:
public static String ShowAllErrors<T>(this HtmlHelper helper) {
StringBuilder sb = new StringBuilder();
Type myType = typeof(T);
PropertyInfo[] propInfo = myType.GetProperties();
foreach (PropertyInfo prop in propInfo) {
foreach (var e in helper.ViewData.ModelState[prop.Name].Errors) {
TagBuilder div = new TagBuilder("div");
div.MergeAttribute("class", "field-validation-error");
div.SetInnerText(e.ErrorMessage);
sb.Append(div.ToString());
}
}
return sb.ToString();
}
Where T is the type of your "ViewModel".
Got this from BrockAllen's answer that worked for me, it displays the keys that have errors:
var errors =
from item in ModelState
where item.Value.Errors.Count > 0
select item.Key;
var keys = errors.ToArray();
Source: https://forums.asp.net/t/1805163.aspx?Get+the+Key+value+of+the+Model+error