I have a session in my Login Controller and there i send List of details via Session to the another page.So i need to take one item of the list to show in mvc view(Actially i need to show UserName in my mvc view).
My Controller
public ActionResult Login(User usrdtl, string returnUrl)
{
//some code here
List<UserDtl> usrList = newsManager.GetUserdetailsByuId(usrdtl.uId);
System.Web.HttpContext.Current.Session["UsrSession"] = usrList ;
}
This usrList consist of lots of user details,i need to show UserName in my view.
In my view i tries to take it as,
<span>#Session["UsrSession"] </span>
But it shows me error
System.Collections.Generic.List`1[NTL.Sys.Entities.UserDtl]
How can i get this ?
It actually does not show you error. It shows the object representation by calling .ToString() on the object.
In your case, Session["UsrSession"].ToString() returns System.Collections.Generic.List1[NTL.Sys.Entities.UserDtl].
Your code actually has no problem at all, modify it to show exactly what you want to show.
I assume that the list contains exactly 1 item. To show the UserName, try:
<span>#((Session["UsrSession"] as List<UserDtl>).First().UserName) </span>
How to show the list is up to you, if you want to display a list of Users, just loop through it. The above code is just an example.
Related
Currently I have a view that has just a single form with three values. When a user submits the form with those three values, my controller checks if all three values actually have a value other than being empty, and if they do then it calls my service that fetches data.
public IActionResult Index(string clientName = "", string tableName = "", string date = "")
{
if (!string.IsNullOrEmpty(clientName) && !string.IsNullOrEmpty(tableName) && !string.IsNullOrEmpty(date))
{
// Unimportant stuff for setting temp variables for FetchData parameters removed
TheData = _fieldDataService.FetchData(tempAcr, tempID, tableName, date, numRows);
}
return View(TheData);
}
My goal is to make the view display a loading icon or something while the data is being fetched. I've looked into JQuery and Ajax but I have no experience with either and cannot figure out how to apply them to my specific task. Since I am using Asp.Net Core, I also looked into using Blazor, but I couldn't wrap my head around it either.
Could somebody point me in the right direction as to what I should/could use to solve this problem? I have a vague understanding that there needs to be some sort of asynchronous function that retrieves the data, but nothing more than that.
You need to fetch the data with JavaScript and manipulate the UI to show a loader. But anyway, a request like this should be so fast, that you don't even need a loader.
I'm also a bit worried that you are passing a tableName as input parameter. You aren't just string concatenating the query right? You might be susceptible to SQL injections, see https://en.wikipedia.org/wiki/SQL_injection.
To do a request with JavaScript, look into the XMLHttpRequest, see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest, or the new way of doing it with fetch(...), see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch.
This answer shows a more practical example: Display loading image while ajax fetches file content.
To give some context on what I know. I learn some time ago from this tutorial even when you set a field from your model READ ONLY on the View how easy is use tools like fiddler to alter the POST data and change the value.
What you do in this case is use Model Binding to specify the list of fields you want Edit and ignore the rest
[HttpPost]
[ActionName("Edit")]
public ActionResult Edit_Post(int id)
{
EmployeeBusinessLayer employeeBusinessLayer = new EmployeeBusinessLayer();
Employee employee = employeeBusinessLayer.Employees.Single(x => x.ID == id);
UpdateModel(employee, new string[] { "ID", "Gender", "City", "DateOfBirth" });
^^^ Name isnt updated
if (ModelState.IsValid)
{
employeeBusinessLayer.SaveEmployee(employee);
return RedirectToAction("Index");
}
return View(employee);
}
Now I learn about Authentication using AspNet.Identity.
Can check if user isn't authenticated to send him to the Login page.
If user belong to certain Role, I can show personalized menus.
Or check the list of contacts for the user and show only those.
But even if you filter the list of contacts based on the user_id before create the view you can access the actions EDIT and DELETE using links like this.
http://MVCDemo/Employee/Edit/1
http://MVCDemo/Employee/Delete/1
And as long you are authenticated, you can change other users data.
So, how you integrate authentication with CRUD actions to avoid unintended actions?
Seem to me to solve this situation I have to apply something similar to the Model Binding example. When get and Edit or Delete post request, first get the Employee from the DB using the id and compare if belong to the current user.
But that create a lot of repeats code across all the functions.
So what is the right way to handle this?
EDIT
To try to make it clear. Lets assume I have an address book application. Each user have contacts:
contact_id user_id name phone ....
1 1 A
2 1 B
3 1 C
4 2 D
5 2 E
6 2 F
The action to show contacts use authenticated user_id to filter the contacts before send it to the view.
Then you have an Edit/Delete actions where you get contact_id and process to Update/Delete. Even when both users have permission to these actions they shouldn't be able to affect other users contacts. But as I explain is very easy change the page using a tool like fiddler.
I can only speak from personal experience but I don't know any MVC features for managing this for you; I've only ever taken the approach you outline of retrieving the data model from the database and explicitly writing the logic to check if the current user has permissions to modify this resource, returning a 401 error if not.
You can compare the incoming request userid with the userid you have in the session, encrypted cookie or web tokens like jwt which ever you use.
Usually if i have load balancer i use encrypted cookie where i store the logged in user's id and compare it with the id i am getting from the request. if both match, update/delete profile else return Unauthorized.
Same can be done in case of Session or tokens as well.
I am very new to MVC in general, so this might sound very silly. However, I don't quite get how to connect my data in the following scenario:
I am creating a project where I have basically two tables
Table 1
pid | pname | etc
Table 2
id | pid | etc
Now, I have successfully implemented a controller where I populate a list with the data in table 1 using "date range" as a parameter.
URL 1
/table1object?search=Search&endDate=2015-02-20&fromDate=2015-02-20
As the tables shown, each row in this view is connected to a certain row in table 2. So, for this I am generating a link which basically sends me to the details of the second controller by looping through the current model.
#Html.ActionLink("Details", "Details/" + #result.pId, "table2Object", null)
Now, my controller number 2 (Details) is only accepting an id to display that specific information of the Table 2.
URL 2
/table2object/Details/96
The Question
Since I am only passing this id to access the second controller, I am going to be able to see only one item at a time. What if I want to add a previous and next buttons to navigate through items in the second controller, but in the range established in the first controller? How can I do this?
Thank you
A first way to do it without respecting any best practices is to save your search result (Controller1) inside a Session variable.
Session["CurrentResult"] = YourViewModelInController1 ;
and then in Controller 2
ActionResult Details(int id)
{
var prevViewModel = Session["CurrentResult"] ;
// Do what you want to find the prev and the next from prevViewModel
}
Of course you can't get the next and the prev if you access your DetailController without displaying table1.
And also, there will be many side effects. e.g : when user make 2 search at once, ..
The second good and correct way to do it, is to re-execute a search to find the previous and the next on Controller 2 Details. Independently of the previous
ActionResult Details(int id)
{
// Do a real search to find the next and the previous
}
Considering you have the idea how to pass values and work in a controller, i can give you a suggestion as below:
You can load your items in a list within a given date range first. Pass that list to 2nd controller And then traverse that list by clicking prev and next using a counter.
Hope this helps,
Thanks
I would like to amend data before it reaches my controller.
We've altered model binders etc through the solution and so amending those isn't an option for me at this time - I'd like to know however if its possible to amend the value being entered before it hits the controller:
Razor code (inside a foreach):
#Html.EditorFor(x=>x.Value);
I've tried things like .Replace(...) but doesn't allow me to amend it that way.
I appreciate what best practice is but time being involved I would like the quick solution and change for the right solution later... Im sure everyone can appreciate that one!
Controller code: (this is why - I need to strip the comma out (which is acceptable in the field, so cant use logic to stop it - I want to replace it with something so I can keep my comma delimited postback)
(formData is of type FormCollection)
var arrayOfValues = formData["x.Value"].Split(',');
So as its a comma delimited value - sometimes that value will be Fred Jones, 1 New Street -> perfectly acceptable entry for what I need, however destroys my comma delimited response.
Any help would be hugely appreciated. This isn't my area of preference at all!
If you want to amend before it hits your controller, you will need to use Javascript/Jquery to catch the form submit and then amend the value before performing the submit.
You could always change the model in the post method, but bear in mind that the modelstate will be used under the hood if you want to check for any errors or send the model back the view.
If you go this route and change the model in the controller then look at clearing the changed field in the modelstate or clearing the whole modelstate before going back to the view, otherwise you won't see your changes and you need to get the model and modelstate to rebind:
model.field1 = newval;
ModelState.Remove("field1");//forces rebind
or
model.field1 = newval;
ModelState.Clear();//clears modelstate fully
Actually in my application there are two type of searching facility one is Quack search and another is Advance search
and i use routing the url means when i use Quack search with computer then my url is
1) http://www.example.com:1270/Computer-Company/Computer/1
we have more TABS or BUTTON on screen like Projects,Services,Leads....etc by default selected company TABS/BUTTON you can click on any tabs/button
suppose you search with computer then by default company is searching, then you can click on Project, you can see the result computers project and url is like below
Computer-Projects/Computer/
and pagination is working also fine Because we have only one Searching text like computers
But my problem is in Advance search
THERE ARE THE TWO TYPE OF PROBLEM
=> when i search with multiple criteria like Company Name,Contact Person,Tags,....etc
User may be search with all criteria or single criteria so ADVANCE SEARCH URL IS LIKE
3)http://www.example.com:1270/AdvanceSearch/Company/1
so please let me know how can i pass the all data from view to controller at pagination time.
so please let me know how can i pass the data from view to controller with the use of model
Temporary i am passing hidden data,But in controller side parameters write like
public ActionReslut Company(string companyName,string contactPerson,string country.....)
{
that is not proper way
}
You should use a ViewModel that contains all the fields that you need in the search:
public class SearchParameters{
string companyName {get;set;}
string contactOerson {get;set;}
string country {get;set;}
....
}
Your action:
public ActionReslut Company(SearchParameters searchParameters)
and then using these fields to filter your data.