Make ActionLink to specific user - asp.net-mvc

How do I make the links on the site lead to the current user's page(s)? I dont want them to get lists of every user but only themselves. I'm thinking something like this for my menu links:
#Html.ActionLink("My Details", "Details", "Customers", Membership.GetUser().ProviderUserKey)

I think it's better if you send user to "My Details" page without any parameter or route values.
The page is going to show current users data. So why to pass it like this?
Just Redirect user to "My Detail" page, and after that, when user is in that page, you can get current user using: HttpContext.CurrentUser.
Don't put user data in route values. Instead you can get it in that page's controller and pass it to the page.

If you want the "Links" to display to show when the page is viewed by an authenticated user, create a ChildAction that returns the data you want like:
[Authorize]
[ChildActionOnly]
public ActionResult UserLinks() {
var items = someRepository.GetLinks(User.Identity.Name);
return PartialView(items,"SomePartialView");
}
Then, use the RenderAction in the view like so:
#{ Html.RenderAction("UserLinks");}
Secondly, I agree with the comment by "Afshin Gh". Rather than passing data in your "ActionLink(s)", you could code it in your Controller to filter the data as required - like I'm showing in the "UserLinks" method above. This way, someone can't just manipulate the Url to display data for another customer.

Related

Hiding URL Parameters from Controller to View: MVC 5

Say I have a website with a wide variety of different pages, each tailored for an individual user and accessible only by that user. When a user accesses a page, the URL for that page will be UserStuff/Pages/11, where 11 is the page's ID. Right now, because users can have multiple pages, I am using an ActionLink element to direct the user to their selected page, like so:
// In Index.cshtml
// ...
#Html.ActionLink("View Page", "Pages", new { id = page.ID }, new { #class=...})
The controller intercepts the given id:
public ActionResult Pages(int id)
{
// ...
Page page = db.Pages.Find(id);
return View(page);
}
This works well and delivers exactly how I want the application to behave. However, I wish for the ID to be hidden in the URL. How do I pass information from the View to the controller via a parameter without having it exposed in the URL? Say that I don't want the Page's ID visible in the URL, how can I link to a different Action that takes the given parameter?
I believe that keeping the request a GET request is important due to other actions redirecting to the resulting page. Wrapping it in a form/POST request would make said actions unable to access the information without having to go through the same process as the original user, which is not something that I want in this implementation.

How to call method of a controller from View without using ajax in ASP.NET MVC?

I am developing MVC application.
I am in situation that, I want to call the method of controller from View.
I don't want to use the Submit button (If I use it goes to create method.) either I dont want to use ajax ....
I want to know that what are ways to call the method of controller from view...
Other than submitting form process or other than ajax call.
Ex. I have a form in which user fills all the data and save it... After submit button it saves the data in DB and Saved data displayed. Now, After saving I want to transfer/pass that data from that view to another view... but I cant find appropriate method for it.
Please check image below...
I have this view after saving...now when I click on 'Click Here' Link , I want to pass the same data to another view to show the preview... some other format...
So I am stuck on how to pass the same data ? I cant use submit as it already saved... I cant use ajax as its not partial stuff... I want to pass the entire to to another view...
If you have the order saved in a database on the server, you would typically pass through the ID, rather than the "entire data" to the controller method, and reload the data from the DB in order to render the other view. Is this what you're after?
View code:
...sent successfully. #Html.ActionLink("Click Here", "Status", new { id = Model.Id }) to check status
Controller Code:
public ActionResult Status(int id)
{
var order = Repository.Get<Order>(id);
return View(order);
}

Passing and Storing objects between Pages

I'd like some advice on this issue. Basically, I have 2 pages (for simplicity sake), and the second page is completely dependent on the first page.
So lets say the main page is a search page, and the second page is a view page.
The site works off XML requests, and the ultimate aim is to keep the XML requests to a minimum as each request is a little slow. I considered using Sessions, but I've had some problems in the past with sessions being mixed between users randomly which i only manage to curb by changing the recycle process in IIS to a very small time frame, so I'm wondering if there is any other way. I've tried TempData, but that expires after one request, so a page refresh on the view page doesn't seem possible. (or is it?)
Anyways, we have the Search page that has, say, 5 attributes that are required by the View page, but only 2 are needed to make the XML request on the view page.
e.g.
Search Page Contains:
ID,
Name,
City,
Email,
Height
View Page needs the following from the Search page to complete the xml request:
ID,
Name,
Email
View Page displays all the information from the search page, plus everything in the XML response.
The link i have in the search page only has the ID in the url, so name and email are required for the XML request on the second page some how. Not sure if it's possible without sessions?
What i've tried is:
Store the search results in TempData. That way, when someone clicks the 'View' link (View), the View page loads the search results like so:
var viewPage = SearchResults.Where(w => w.ID == id).FirstOrDefault();
The ViewModel then renders the page by grabbing the Name and Email from viewPage, making an XML request, and displaying the response, along with other required details from viewPage.
It works as expected with tempdata. Data only persists on the first request, dies on a page refresh. Sessions is the alternative, but is there any other?
(sorry for the wall of text :)
Why not using more standard techniques like a <form> tag in the search page pointing to the controller action that will perform the search:
#using (Html.BeginForm("search", "somecontroller", FormMethod.Get))
{
... some input fields for your search criteria
<button type="submit">Search</button>
}
and then you will have the Search controller action:
public ActionResult Search(SearchModel model)
{
var results = ....
return View(results);
}
I've used GET method on the form which allows the user to bookmark the results page and come back to it later.

asp.net-mvc - how do i create a view to show all unapproved users and allow them to be approved

i have this code in my membership service class (taken from the asp.net-mvc sample app)
public MembershipUserCollection GetUnapprovedUsers()
{
MembershipUserCollection users = Membership.GetAllUsers();
MembershipUserCollection unapprovedUsers = new MembershipUserCollection();
foreach (MembershipUser u in users)
{
if (!u.IsApproved)
{
unapprovedUsers.Add(u);
}
}
return unapprovedUsers;
}
i now need a view to show this list of information and allow someone to approve them which will go back to the controller and set the IsApproved property to true.
Create a view which will generate a form containing label and checkbox for each member of the collection. You need to be able to get from the id of the checkbox to the user.
In the HTTP.POST Action method, iterate through the submitted fields looking for set checkboxes, when you find one set the corresponding user to approved.
Obviously the form can display arbitrary details for each user.
To use the inbuilt control helpers takes a bit more effort because you don't have a fixed size model to work with. To achieve something similar I:
Used a non-strongly typed view
populated ViewData["ids"] with IEnumerable<IdType> (which the view would loop over)
For each entry populated ViewData["field" + id] for each field I was displaying in the entity
In the view looped over the ids using ViewData["ids"] to call the HTML helpers with the id of the field.
(That was V1, in V2 I used model state so I could use the inbuilt validation error display support, but that doesn't really apply if you just want to select users.)
The POST processing was similar, repopulating the id list from the database and the looking up in the passed FormCollection.

How can I create 1 route with 2 differents user's access in ASP.NET MVC?

How can I do this: I have on page named "Schedule" and it can be accessed through 2 differente ways:
URL 1- www.bla.com/Admin/Schedule
URL 2- www.bla.com/Schedule
"URL 1" will be accessed by users with Admin previlegies and this View will show some Admin stuff, and users must be LoggedOn.
In the otherhand, "URL 2" will be accessed by users NOT LoggedOn and it will NOT show the admin stuff.
But, they are the same page, just with some differences depending on user's access.
I already have AdminController and I intend to put this "Schedule" View as part of this controller. As result, I know if I type "URL 1" it will work. But, if I type "URL 2"? Will I have to create a "ScheduleController" just to handle this?
I wonder if there is a way to resolve this by Global.asax, configuring the routing... I don't know...
Thanks!!!
You can map the /Schedule route to the /Admin/Schedule action from the Global.asax.cs like this:
routes.MapRoute(
"Schedule",
"schedule",
new { controller = "Admin", action = "Schedule" }
);
This will solve your immediate problem of wanting two separate routes resulting in the same action/view.
However, this will not solve your scenario properly. The main issue is that the identity of the logged on user is orthogonal to the route the request takes. In other words, you can't force the admin user to always hit the /Admin/Schedule route, they could just as well hit the /Schedule route and still would expect the same end result. Not only that, but doing it this way will prevent you from using the [Authorize] attribute on the Admin controller or the action to force the user to login and will have to implement custom logic checking which route the action was hit through and decide whether you want to force login or let the user through.
Thus, you have to make a decision:
you share the controller, action and the view and determine whether to show the additional information in the view based on the identity and the role membership of the logged on user (if any). You will have to change the name of the controller then, as /Admin will not reflect the new role this class has;
you share only the view and have two separate controllers and actions - Admin.Schedule and User.Schedule. You will have to put the view in the /views/shared folder and return the same view fromboth actions, potentially passing different model. You'll end up with two routes - /Admin/Schedule and /User/Schedule;
you have two separate controllers, actions and views.
In all three cases, you can still have the rule above pointing to the appropriate controller, if you want to have also the shortest /Schedule route.
Make the View shared and just render it from both controller actions. Pass the appropriate data via the model (or ViewData) so the View knows not to render the admin stuff when rendered from the non-admin controller action.
And, yes, create the Schedule controller. Make the routing simple and handle sharing the generation code on the back end.
AdminController
public ActionResult Schedule( ... )
{
Schedule sched = ... get model ...
return View("Schedule", new SchedViewModel {
Schedule = sched,
Admin = true
} );
}
ScheduleController
public ActionResult Index( ... )
{
Schedule sched = ... get model ...
return View("Schedule", new SchedViewModel {
Schedule = sched,
Admin = false
} ); }
Sounds like you don't really need a different URL if it's the same page. However if for some reason you still want to use 2 different URLs...
Url 1:
routes.MapRoute("ScheduleAdmin", "Admin/Schedule",
new
{
controller = "AdminController",
action = "Schedule"
});
Url 2:
routes.MapRoute("Schedule", "Schedule",
new
{
controller = "ScheduleController",
action = "Index"
});
You didn't make it clear what action you were using for the schedule controller so feel free to change that.

Resources