MVC pass query strings - model-view-controller

I am new to Microsoft.MVC, so sorry if this is a silly question.
I have created a very simple forum, and I am now trying to create some tag functionality to it.
I have a controller where the index retrieves the last 10 forum threads. I would like to pass a query string, or something a-like with the Id to the supplied tag to the forum, so I thereby can get the forum threads, which e.g. have the tag 'ASP.NET'.
If it was a regular webforms project I would simply supply a query string with the tag id, to the index page, and then retrieve the forum threads with the tag, but isn't there a smarter way to do it in MVC.NET?
The reason why I ask, is it seems like a step backwards from REST-urls, to suddenly use 'regular' query strings?

First you define your action (like you probably already did), and add the parameters like you need them:
public ActionResult Forum(string tag, int page)
{
// do your thing
// ...
return View();
}
Then, in your Global.asax.cs, you can add a route that handles the parameters like you want them.
routes.MapRoute("Forum", "Forum/{tag}/{page}", new {controller = "Home", action = Forum"});
This will cause the Forum action to trigger on the HomeController when you go to the http://yourhost/Forum link. If you then click have a link like this http://yourhost/Forum/asp.net/1 Then "asp.net" will passed into the tag parameter, and 1 will be passed onto the page parameter.

You can use an ActionLink html helper. Assuming you have a forums controller and index page, to get a link to /forums/index/1?tag=asp.net you can do:
Html.ActionLink("ASP.NET", "index", new { id = 1, tag = "asp.net"})

Related

Creating a filtered search based on different parameters

i need to create a filtered search based on different paramnters chosen by a user. So, for example, my app is a property app. I want them to be able to define the county, town, max,min bedrooms ect from a dropdown list and press search, and this returns all the properties that match the criteria.
How do I go about doing this? I can't find any tutorials online, but maybe I'm not phrasing it right.
Here is an image of what I'm after from a UI point of view.
https://imgur.com/a/YEEqt
The following is an easy to go solution considering your experience.
Create a new controller or a method in an existing one.
First create a simple form (method GET) in blade that will return predefined values from simple hidden fields
Create a new GET route in which the form must be submitted and link it to the controller method that you created
In your controller method get the submitted form data from your request, make the correct queries and return the blade template file that contains the form with the results
Modify blade template to show results
Finally replace the hidden fields with selects drop-downs and modify your controller in order to populate them
You can make the form submission process and the select drop-down fields population asynchronous but based on your experience with Laravel it should be hard. Following the steps above will do your job.
Always take a look to the official documentation. You will ge a lot of help from there.
You can try like this for filter options in your controller
public function filter(Request $request, Property $property)
{
$property = $property->newQuery();
// Search for a property based on country
if ($request->has('country')) {
return $property->where('country', $request->input('country'));
}
// Search for a property based on their area.
if ($request->has('areas')) {
return $property->where('areas', $request->input('areas'));
}
// Search for a property based on max_price
if ($request->has('max_price')) {
return $property->where('price','<=', $request->input('max_price'));
}
// Continue for all of the filters.
return $property->get();
}
For more info refer the link

How do I bypass the limitations of what MVC-CORE controllers can pass to the view?

From what I've read, I'm supposed to be using ViewModels to populate my views in MVC, rather than the model directly. This should allow me to pass not just the contents of the model, but also other information such as login state, etc. to the view instead of using ViewBag or ViewData. I've followed the tutorials and I've had both a model and a viewmodel successfully sent to the view. The original problem I had was that I needed a paginated view, which is simple to do when passing a model alone, but becomes difficult when passing a viewmodel.
With a model of
public class Instructor {
public string forename { get; set; }
public string surname { get; set; }
}
and a viewmodel of
public class InstructorVM {
public Instructor Instructors { get; set; }
public string LoggedIn { get; set; }
}
I can create a paginated list of the instructors using the pure model Instructor but I can't pass InstructorVM to the view and paginate it as there are other properties that aren't required in the pagination LoggedIn cause issues. If I pass InstructorVM.Instructors to the view, I get the pagination, but don't get the LoggedIn and as this is just the model, I may has well have passed that through directly.
An alternative that was suggested was to convert/expand the viewmodel into a list or somesuch which would produce an object like this that gets passed to the view
instructor.forename = "dave", instructor.surname = "smith", LoggedIn="Hello brian"
instructor.forename = "alan", instructor.surname = "jones", LoggedIn="Hello brian"
instructor.forename = "paul", instructor.surname = "barns", LoggedIn="Hello brian"
where the LoggedIn value is repeated in every row and then retrieved in the row using Model[0].LoggedIn
Obviously, this problem is caused because you can only pass one object back from a method, either Instructor, InstructorVM, List<InstructorVM>, etc.
I'm trying to find out the best option to give me pagination (on part of the returned object) from a viewmodel while not replicating everything else in the viewmodel.
One suggestion was to use a JavaScript framework like React/Angular to break up the page into a more MVVM way of doing things, the problem with that being that despite looking for suggestions and reading 1001 "Best JS framework" lists via Google, they all assume I have already learned all of the frameworks and can thus pick the most suitable one from the options available.
When all I want to do is show a string and a paginated list from a viewmodel on a view. At this point I don't care how, I don't care if I have to learn a JS framework or if I can do it just using MVC core, but can someone tell me how to do this thing I could do quite simply in ASP.NET? If it's "use a JS framework" which one?
Thanks
I'm not exactly sure what the difficulty is here, as pagination and using a view model aren't factors that play on one another. Pagination is all about selecting a subset of items from a data store, which happens entirely in your initial query. For example, whereas you might originally have done something like:
var widgets = db.Widgets.ToList();
Instead you would do something like:
var widgets = db.Widgets.Skip((pageNumber - 1) * itemsPerPage).Take(itemsPerPage).ToList();
Using a view model is just a layer on top of this, where you then just map the queried data, no matter what it is onto instances of your view model:
var widgetViewModels = widgets.Select(w => new WidgetViewModel
{
...
});
If you're using a library like PagedList or similar, this behavior may not be immediately obvious, since the default implementation depends on having access to the queryset (in order to do the skip/take logic for you). However, PagedList, for example has StaticPagedList which allows you to create an IPagedList instance with an existing dataset:
var pagedWidgets = new StaticPagedList<WidgetViewModel>(widgetViewModels, pageNumber, itemsPerPage, totalItems);
There, the only part you'd be missing is totalItems, which is going to require an additional count query on the unfiltered queryset.
If you're using a different library, there should be some sort of similar functionality available. You'll just need to confer with the documentation.

MVC3 -- Adding additional items to List<> with Jquery

I have a view model that looks like this:
HomeViewModel hvm = new HomeViewModel();
hvm.Applicant = new Person();
hvm.Applicant.Residences = new List<Residence>();
hvm.Applicant.Residences.Add(new Residence() { Type = "Current" });
In my .cshtml page, I have:
<label>Street # *:</label> #Html.TextBoxFor(m => m.Applicant.Residences[0].StreetNumber)
And so on and so forth for my properties in my Residence model. However, I want the user to be able to add multiple residences(previous, secondary, other, etc). I can add the necessary form fields via jquery, however, since the model doesn't know about the new list items, I get an error about null objects. The front end may be adding numerous residences via jquery.
This is a surprisingly complex topic. Check out the blog series starting with http://ivanz.com/2011/06/16/editing-variable-length-reorderable-collections-in-asp-net-mvc-part-1/
Try this: http://archive.plugins.jquery.com/project/jquery-dynamic-form
View demo here: http://sroucheray.org/blog/jquery-dynamic-form/

Achieving product/Apple-ipad in place of product/Index/23

I wasn't able to put the write words for the Title, so I explained what I'm looking after.
Currently, I am using following ActionLink code in View.
#Html.ActionLink(#product.Name, "Index", "Product", new { id = #product.Id }, null)
This code redirects to following action method in Product Controller
public ActionResult Index(int id)
{
Product product = pe.Products.Where(p => p.Id == id).First();
ViewBag.Title = product.Name;
ViewBag.Description = product.MetaDescription;
ViewBag.Keywords = product.MetaKeywords;
return View(product);
}
Now, what i want: instead of mysite.com/Product/Index/22 , my URL should be something like mysite.com/Product/Apple-ipad.
I know, I can use product Name instead of Id and pass it to the action method. But, this way i think that the queries will get slower since Id field is indexed but Name isn't. Is this the only option at my disposal. Let me know how will you handle this requirement.
Use the product name in the route instead of ID and put a nonclustered index on the product name column in the database.
That way you don't get a performance hit on the select (although you will get one on the insert/update/delete but I suspect those happen far less than the selects).
CREATE INDEX IX_[index_name]
ON [schema].[table_name] ([column_name]);
Another way I've seen used in a few places is using both the name and the id like mysite.com/Product/Apple-ipad/22. The name is not actually used by the code, and it's just there for SEO. One big disadvantage of this is that someone that does not like your site can put various urls leading to the same content all over the internet for google to find. Google doesn't like that so your site is penalized and you are worse than before.

ASP.NET MVC go back to correct view

I have Person controler with List Edit Create methods after edit of Person i go back to Person list
NOW I have other controler Family (Family - Person is one-to-many )
on Detail Family I have list of Persons with edit linked to Person/Edit/Id
When user clicks Save Person after editing I want to go back to Family Detail if he came from there or to Peron list if he Edited Person from Person list
Some help please
Thanks
You can use
HttpContext.Request.UrlReferrer
So to go back to the last view you would use something like:
Response.Redirect(HttpContext.Request.UrlReferrer.OriginalString);
Edit after comment:
Indeed you would get send back to the edit page in this case, what you could do if you don't want anyone to see querystrings is: (assuming you are using html.form to post the data).
On your Edit person page, inside of the form add something like:
#using (Html.BeginForm(new { RedirectUrl = HttpContext.Current.Request.UrlReferrer.OriginalString } )
and then on the controller pick it up as:
public Void Edit(int id, string RedirectUrl)
{
//save stuff
return Redirect(RedirectUrl);
}
You can pass the URL of the previous page in the query string for the edit page.

Resources