Need a Search Form/Search Box To Get related data or Exact data by any Keyword in Umbraco 10 - umbraco

Page Code:
#page "/search"
#using WebApplication1.Shared.Models;
#using WebApplication1.Shared.Services;
#inject IContentDeliveryService _contentDeliveryService;
<EditForm Model="#searchModel" OnSubmit="Search">
<InputText id="SearchTerm" class="form-control" #bind-Value="searchModel.SearchTerm" />
<button type="submit" class="btn btn-success">Submit</button>
</EditForm>
<div>
#if (publishSearchResults != null)
{
foreach (var item in publishSearchResults)
{
<ul>
<li>item</li>
</ul>
}
}
</div>
private SearchModel searchModel = new SearchModel();
public string searchterm;
List<Umbraco.Cms.Core.Models.PublishedContent.PublishedSearchResult> publishSearchResults = new ();
protected async Task Search()
{
var data = _contentDeliveryService.Search(searchModel.SearchTerm);
publishSearchResults =
data.Cast<Umbraco.Cms.Core.Models.PublishedContent.PublishedSearchResult>
().ToList();
}
Service Code:
public IEnumerable<PublishedSearchResult> Search(string searchTerm)
{
using var scope = _scopeFactory.CreateScope();
var myService = scope.ServiceProvider.GetRequiredService<Umbraco.Cms.Core.IPublishedContentQuery>();
foreach (var result in myService.Search(searchTerm))
{
yield return result;
}
}
Getting Exception:
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: No service for type 'Umbraco.Cms.Core.IPublishedContentQuery' has been registered.
System.InvalidOperationException: No service for type 'Umbraco.Cms.Core.IPublishedContentQuery' has been registered.
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[IPublishedContentQuery](IServiceProvider provider)
at WebApplication1.Shared.Services.ContentDeliveryService.Search(String searchTerm)+MoveNext() in D:\Clients\Kim\Softnotik.Web\Shared\Services\ContentDeliveryService.cs:line 562
at System.Collections.Generic.List1[[Umbraco.Cms.Core.Models.PublishedContent.PublishedSearchResult, Umbraco.Core, Version=10.2.0.0, Culture=neutral, PublicKeyToken=null]]..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[PublishedSearchResult](IEnumerable`1 source)
at WebApplication1.Client.Pages.AboutUs.SearchComponent.Search() in D:\Clients\Kim\Softnotik.Web\Client\Pages\AboutUs\SearchComponent.razor:line 39
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.Forms.EditForm.HandleSubmitAsync()
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
window.Module.s.printErr # blazor.webassembly.js:1
DevTools failed to load source map: Could not load content for chrome-extension://gpaiobkfhnonedkhhfjpmhdalgeoebfa/editor/config.js.map: System error: net::ERR_BLOCKED_BY_CLIENT
DevTools failed to load source map: Could not load content for chrome-extension://gpaiobkfhnonedkhhfjpmhdalgeoebfa/editor/content.js.map: System error: net::ERR_BLOCKED_BY_CLIENT
search:1 Failed to load resource: the server responded with a status of 500 (Internal Server Error)

This is not a very good question. You aren't asking anything. You don't really describe what you have tried, other than some bits of code out of context. You don't provide us with much info to help you figure it out. And that's what we want to do - we don't want to write your code for you, we want you to figure out how to do it yourself :-)
That said, have you looked at https://docs.umbraco.com/v/10.x-lts/umbraco-cms/implementation/services ? I can't see the context of your "Service code" method - is it in an actual service? In a controller? - but the docs say this:
Trying to inject types that are based on an Http Request such as
UmbracoHelper or IPublishedContentQuery into classes that are not
based on an Http Request will trigger an error. However, there is a
technique that allows the querying of the Umbraco Published Content,
using the UmbracoContextFactory and calling EnsureUmbracoContext().
So if your code is in a service object and doesn't have an HttpContext/UmbracoContext of sorts, it might need it via UmbracoContextFactory.
But it's pretty much a blind guess, I'm afraid. Maybe it'll get you closer to being able to search.

Related

IIS returning default Error HTML instead of JSON, as instructed

I made a custom Attribute for certain endpoints in my ASP.NET MVC project, that instructs the server to return a JSON object, instead of handling the errors the usual way. The Attribute looks like this:
public class AjaxErrorHandler : FilterAttribute, IExceptionFilter
{
public void OnException(ExceptionContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.ExceptionHandled = true;
filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
filterContext.HttpContext.Response.StatusDescription =
filterContext.Exception.Message.Replace('\r', ' ').Replace('\n', ' ');
filterContext.Result = new JsonResult
{
Data = new { errorMessage = filterContext.Exception.Message }
};
}
}
}
Whenever I debug the solution locally, it works just fine, and returns the following on error:
{"errorMessage":"Error message goes here"}
But when I deploy the solution to my production server, the server consistantly returns the following HTML:
#content{margin:0 0 0 2%;position:relative;}
.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}
-->
</style>
</head>
<body>
<div id = "header" >< h1 > Server Error</h1></div>
<div id = "content" >
< div class="content-container"><fieldset>
<h2>500 - Internal server error.</h2>
<h3>There is a problem with the resource you are looking for, and it cannot be displayed.</h3>
</fieldset></div>
</div>
</body>
</html>
What configuration of the web project am I missing here, to make the server honor the instruction to return the JSON object?
I have seen this before with IIS.
From memory, you could try this:
Open the IIS Mgr
Select the website in question
Double click error pages icon
Click edit feature settings on the right hand side
Change the setting to detailed errors for local and custom error pages for remote requests
Try the site again
Think that was how I got around it in the past

How to do File Upload Without Page Refresh or redirect in ASP.NET MVC

I am uploading a file using via a view linked to a controller however after the upload is uploaded the application is either trying to refresh or redirect and I need to prevent this. May you please point me in the right direction to avoid redirection and refresh? I have done a bit of reading and I suspect that this line action="/api/BulkUpload">might be causing the problem.
My Controller
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using Repositories.BulkUpload;
using Repositories.Interfaces.BulkUpload;
namespace SimSentinel.Controllers
{
//[Authorize]
public class BulkUploadController : ApiController
{
private readonly IBulkUploadRepository _bulkUploadRepository;
public async Task<HttpResponseMessage> PostFile()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/Files");
var provider = new FormDataStreamer(root);
try
{
StringBuilder sb = new StringBuilder(); // Holds the response body
// Read the form data and return an async task.
await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the form data.
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
sb.Append(string.Format("{0}: {1}\n", key, val));
}
}
// This illustrates how to get the file names for uploaded files.
foreach (var file in provider.FileData)
{
FileInfo fileInfo = new FileInfo(file.LocalFileName);
sb.Append(string.Format("Uploaded file: {0} ({1} bytes)\n", fileInfo.Name, fileInfo.Length));
}
return new HttpResponseMessage()
{
Content = new StringContent(sb.ToString())
};
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
public class FormDataStreamer : MultipartFormDataStreamProvider
{
public FormDataStreamer(string rootPath) : base(rootPath) { }
public FormDataStreamer(string rootPath, int bufferSize) : base(rootPath, bufferSize) { }
public override string GetLocalFileName(HttpContentHeaders headers)
{
var srcFileName = headers.ContentDisposition.FileName.Replace("\"", "");
return Guid.NewGuid() + Path.GetExtension(srcFileName);
}
}
}
}
MY HTML
<form name="form1" method="post" enctype="multipart/form-data" action="/api/BulkUpload">
<div>
<label for="caption">Image Caption</label>
<input name="caption" type="text" />
</div>
<div>
<label for="image1">Image File</label>
<input name="image1" type="file" />
</div>
<div>
<input type="submit" value="ok" />
</div>
</form>
You're correct. When you submit the form, the file is sent to the controller via a HTTP POST request and the page is either, necessarily, refreshed or redirected. If you don't want to the page to refresh or redirect, then you'll have to use AJAX to post the file to the controller.
From a Mozilla Developer document on HTTP requests,
The GET method requests a representation of the specified resource.
Requests using GET should only retrieve data.
The POST method is used to submit an entity to the specified
resource, often causing a change in state or side effects on the
server.
From these notes on Web Programming from Nanyang Technological University,
[The] POST request method is used to "post" additional data up to the server
(e.g., submitting HTML form data or uploading a file). Issuing an HTTP
URL from the browser always triggers a GET request. To trigger a POST
request, you can use an HTML form with attribute method="post" or
write your own network program. For submitting HTML form data, POST
request is the same as the GET request except that the URL-encoded
query string is sent in the request body, rather than appended behind
the request-URI.
So, you can see that since you're posting a file to the server using a standard HTTP request, it is necessarily going to refresh or redirect in some way.
To avoid this, you can use jQuery to asynchronously post the file to the server without refreshing the page. There are plenty of articles on how to do this. I suggest you give it a try and post another question if you get stuck.
Upload file using jQuery and post it to Controller
ASP Snippets - Upload file using jQuery AJAX in ASP.Net MVC
C# Corner - File Upload Through JQuery AJAX In ASP.NET MVC
Thanks so much for the help it guided me in the right direction. I eventually got my answer from this [How to submit html form without redirection? . The Iframe approach is the simplest approach it is a temporary fix seeing as some articles are saying that although it is still supported by most modern browsers it has been deprecated.

asmx web service and MVC 3 - How to use Model and map web service data to it?

I have a web service and I want to display the data from web service in my MVC Razor View.
This is what I have done:
1) My Web Method:
[WebMethod]
public string HelloWorld()
{
return "Hello World... This is a Web Service consumed
through MVC Project";
}
2) Added web reference to my MVC Project
3) View :
<table><tr><td>
<input type="button" id="btnSubmit" value="Get Message"
onclick="javascript:getMessage();" />
</td></tr></table>
<div id="Result"></div>
4) Script in my view
function getMessage() {
var URL = "/Home/getMessage/";
$.get(URL, function (data) {
$("#Result").html(data);
});
}
Note : Controller name is Home and Action Method is getMessage
5) Action Method in Home
public string getMessage()
{
Service1 mvcServiceProxy = new Service1();
string message = mvcServiceProxy.HelloWorld();
return message;
}
I have followed the above steps and I am able to get the message in to my DIV as per my javascript code.
But If I have a model, and the property in my model is like: public string Message{ get; set; }
How can I get the message into this property? DO I need to modify my action method and Javascript? Should I use something like JSON ?
I am not sure of how to achive this...
I just want to use my property and display the content (message) from my web service into my Razor view using my model property instead of passing the html value into DIV and directly displaying it.
Please suggest.
Thanks in advance !!!!
First of all property is basically used to read/modify any private data in a class from another Type.
So what you are trying to achieve shouldn't be done with properties.
The way you are trying is ok, also you can get a complete list of data in one call using Json and set it on html page according to your need.
So I would recommend playing around with Json.

What are the security reasons for not allowing get requests with MVC/ajax? [duplicate]

As part of the ASP.NET MVC 2 Beta 2 update, JSON GET requests are disallowed by default. It appears that you need to set the JsonRequestBehavior field to JsonRequestBehavior.AllowGet before returning a JsonResult object from your controller.
public JsonResult IsEmailValid(...)
{
JsonResult result = new JsonResult();
result.Data = ..... ;
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result;
}
What is the reasoning behind this? If I am using JSON GET to try and do some remote validation, should I be using a different technique instead?
The reason for the DenyGet default is on MSDN with a link to Phil Haack's blog for further details. Looks like a Cross-Site scripting vulnerability.
HTTP GET is disabled by default as part of ASP.NET's Cross-Site Request Forgery (CSRF/XSRF) protections. If your web services accept GET requests, then they can be vulnerable to 3rd party sites making requests via <script /> tags and potentially harvesting the response by modifying JavaScript setters.
It is worth noting however that disabling GET requests is not enough to prevent CSRF attacks, nor is it the only way to protect your service against the type of attack outlined above. See Robust Defenses for Cross-Site Request Forgery for a good analysis of the different attack vectors and how to protect against them.
I also had your problem when I migrated my MVC website from Visual Studio 2008 to Visual Studio 2010.
The main aspx is below, it has an ViewData which calls a Category Controller in order to fill up ViewData["Categories"] with SelectList collection. There's also a script to call a Subcategory Controller to fill up the second combo with javascript. Now I was able to fix it adding up AlloGet attribute on this second controller.
Here's the aspx and javascript
<head>
<script type="text/javascript" src="../../Scripts/jquery-1.4.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#CategoryId").change(function () {
var categoryId = $(this)[0].value;
$("#ctl00_MainContent_SubcategoryId").empty();
$("#ctl00_MainContent_SubcategoryId").append("<option value=''>-- select a category --</option>");
var url = "/Subcategory/Subcategories/" + categoryId;
$.getJSON(url, { "selectedItem": "" }, function (data) {
$.each(data, function (index, optionData) {
$("#ctl00_MainContent_SubcategoryId").append("<option value='" + optionData.SubcategoryId + "'>" + optionData.SubcategoryName + "</option>");
});
//feed our hidden html field
var selected = $("#chosenSubcategory") ? $("#chosenSubcategory").val() : '';
$("#ctl00_MainContent_SubcategoryId").val(selected);
});
}).change();
});
</script>
<body>
<% using (Html.BeginForm()) {%>
<label for="CategoryId">Category:</label></td>
<%= Html.DropDownList("CategoryId", (SelectList)ViewData["Categories"], "--categories--") %>
<%= Html.ValidationMessage("category","*") %>
<br/>
<label class="formlabel" for="SubcategoryId">Subcategory:</label><div id="subcategoryDiv"></div>
<%=Html.Hidden("chosenSubcategory", TempData["subcategory"])%>
<select id="SubcategoryId" runat="server">
</select><%= Html.ValidationMessage("subcategory", "*")%>
<input type="submit" value="Save" />
<%}%>
here's my controller for subcategories
public class SubcategoryController : Controller
{
private MyEntities db = new MyEntities();
public int SubcategoryId { get; set; }
public int SubcategoryName { get; set; }
public JsonResult Subcategories(int? categoryId)
{
try
{
if (!categoryId.HasValue)
categoryId = Convert.ToInt32(RouteData.Values["id"]);
var subcategories = (from c in db.Subcategories.Include("Categories")
where c.Categories.CategoryId == categoryId && c.Active && !c.Deleted
&& c.Categories.Active && !c.Categories.Deleted
orderby c.SubcategoryName
select new { SubcategoryId = c.SubcategoryId, SubcategoryName = c.SubcategoryName }
);
//just added the allow get attribute
return this.Json(subcategories, JsonRequestBehavior.AllowGet);
}
catch { return this.Json(null); }
}
I don't know if this is the reason they chose to change that default, but here's my experience:
When some browsers see a GET, they think they can cache the result. Since AJAX is usually used for small requests to get the most up-to-date information from the server, caching these results usually ends up causing unexpected behavior. If you know that a given input will return the same result every time (e.g. "password" cannot be used as a password, no matter when you ask me), then a GET is just fine, and browser caching can actually improve performance in case someone tries validating the same input multiple times. If, on the other hand, you expect a different answer depending on the current state of the server-side data ("myfavoriteusername" may have been available 2 minutes ago, but it's been taken since then), you should use POST to avoid having the browser thinking that the first response is still the correct one.

Windows Azure ASP.NET MVC Role behaves strangely when redirecting from HTTP to HTTPS

Subj. I've got an ASP.NET 2 MVC Worker Role Application, that does not differ much from the default template.
When attempting redirect from HTTP to HTTPS (this happens when we access constroller secured by the usual RequireSSL attribute implementation) we get blank page with "Bad Request" message.
IntelliTrace shows this:
Thrown: "The file '/Views/Home/LogOnUserControl.aspx' does not exist." (System.Web.HttpException)
Call stack is really short:
[External Code]
App_Web_vfahw7gz.dll!ASP.views_shared_site_master.__Render__control1(System.Web.UI.HtmlTextWriter __w = {unknown}, System.Web.UI.Control parameterContainer = {unknown})
[External Code]
App_Web_bsbqxr44.dll!ASP.views_home_index_aspx.ProcessRequest(System.Web.HttpContext context = {unknown})
[External Code]
User control reference is the usual one in /Views/Shared/Site.Master:
<div id="logindisplay">
<% Html.RenderPartial("LogOnUserControl"); %>
</div>
And partial view LogOnUserControl.ashx is located in Views/Shared (and it is ASCX, not ASPX).
Problem shows up, when we try to access site pages, that require auth (FormsAuth) and redirect because of the SSL. These pages are secured by RequireSSL attribute (Redirect == true):
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public sealed class RequireSslAttribute : FilterAttribute, IAuthorizationFilter
{
public bool Redirect { get; set; }
// Methods
public void OnAuthorization(AuthorizationContext filterContext)
{
// this get's messy, when we are running custom ports
// within the local dev fabric.
// hence we disable code in the debug
#if !DEBUG
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (filterContext.HttpContext.Request.IsSecureConnection)
return;
var canRedirect = string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase);
if (canRedirect && Redirect)
{
var builder = new UriBuilder
{
Scheme = "https",
Host = filterContext.HttpContext.Request.Url.Host,
Path = filterContext.HttpContext.Request.RawUrl
};
filterContext.Result = new RedirectResult(builder.ToString());
}
else
{
throw new HttpException(0x193, "Access forbidden. The requested resource requires an SSL connection.");
}
#endif
}
}
Obviously we compile in RELEASE for this case.
Does anybody have any idea, what could cause this strange exception and how to get rid of it?
NB: that's not the proper solution, but it worked for now. By marking the entire home controller with RequireSsl we force all visitors to use Https from the start.
It is still possible to hit the error by calling something like:
http://project.company.com/User/Login?ReturnUrl=/solution
But it is not likely to get to such a link by navigating the site, so this will work for the time being.
Is there a specific reason your "LogOnUserControl" partial view is an ashx file rather than aspx/ascx? I'm under the impression that MVC only looks for .aspx and .ascx files as a convention.

Resources