Kentico 9 - Separate MVC Application - Document Attachment - asp.net-mvc

I am trying to add an attachment to a document - I am running a separate MVC application - not part of the same solution as the Kentico admin site.
I am getting error site not found for my UserInfo.
public Models.PartnerUpdateModel NewPartnerUpdate(Models.PartnerUpdateModel partnerupdatemodel)
{
CMS.DocumentEngine.TreeNode newpartnerupdatetreenode = CMS.DocumentEngine.TreeNode.New(partnerupdatemodel.KenticoPartnerUpdate.ClassName);
TreeProvider tree = new TreeProvider();
partnerupdatemodel.KenticoPartnerUpdate.Title = partnerupdatemodel.Title;
partnerupdatemodel.KenticoPartnerUpdate.Summary = partnerupdatemodel.Summary;
partnerupdatemodel.KenticoPartnerUpdate.Article = partnerupdatemodel.Article;
partnerupdatemodel.KenticoPartnerUpdate.Author = partnerupdatemodel.MarketConnectUser.UserID.ToString();
partnerupdatemodel.KenticoPartnerUpdate.DocumentCulture = partnerupdatemodel.DocumentCulture;
partnerupdatemodel.KenticoPartnerUpdate.Insert(TreeHelper.SelectSingleNode(partnerupdatemodel.MarketConnectUser.DefaultGroup.GroupChildNodes.Where(x => x.Key == partnerupdatemodel.ParentClassName).Select(x => x.Value).Single()), true);
partnerupdatemodel.KenticoPartnerUpdate.SubmitChanges(true);
foreach (var file in partnerupdatemodel.Files)
{
HttpPostedFile postedfile = FileHelper.ConstructHttpPostedFile(FileHelper.ToByteArray(file.InputStream), file.FileName, file.ContentType);
DocumentHelper.AddAttachment(newpartnerupdatetreenode, Models.PartnerUpdateModel.AttachmentColumnNames.Image.ToString(), postedfile, new TreeProvider(MembershipContext.AuthenticatedUser)); //GETTING ERROR HERE
newpartnerupdatetreenode.Update();
}
return partnerupdatemodel;
}

MembershipContext is not oficially supported in v9 (Supported and unsupported Kentico features on MVC sites) however I think this should work - to be honest I have tried it by myself and I`ve got UserInfo (for public user and global admin too). Could you please provide call stack of exception?
edit: I have also tried to get current SiteInfo like
var site = SiteContext.CurrentSite;
and it`s null if you have not specified Presentation URL - could you check this setting?

Related

How to use SimpleProvider with my own MSAL C# code

I'm trying to use my own MSAL code to work together. Developed with .NET Core 5 MVC.
I have similar problem as I found in below link. But I just don't know how to make it work with the proposed answer. Or in other words, I'm still confuse how this integration is done.
[It is mandatory to use the login component in order to use the other components]It is mandatory to use the login component in order to use the other components
[Quickstart for MSAL JS]https://github.com/microsoftgraph/microsoft-graph-toolkit/blob/main/samples/examples/simple-provider.html
I also have read following article too:
[Simple Provider Example]https://github.com/microsoftgraph/microsoft-graph-toolkit/blob/main/samples/examples/simple-provider.html
[A lap around microsoft graph toolkit day 7]https://developer.microsoft.com/en-us/office/blogs/a-lap-around-microsoft-graph-toolkit-day-7-microsoft-graph-toolkit-providers/
is there someone can pointing to me more details explanation about how to archive this.
Can someone explains further below response further. How to do it. Where should I place the code and how to return AccessToken to SimpleProvider?
Edited:
Update my question to be more precise to what I want besides on top of the question. Below is the code I used in Startup.cs to automatically trigger pop up screen when user using the web app. When using the sample provided, it is always cannot get access token received or userid data. Question 2: How to save or store token received in memory or cache or cookies for later use by ProxyController and its classes.
//Sign in link under _layouts.aspx
<a class="nav-link" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignIn">Sign in</a>
// Use OpenId authentication in Startup.cs
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
// Specify this is a web app and needs auth code flow
.AddMicrosoftIdentityWebApp(options =>
{
Configuration.Bind("AzureAd", options);
options.Prompt = "select_account";
options.Events.OnTokenValidated = async context =>
{
var tokenAcquisition = context.HttpContext.RequestServices
.GetRequiredService<ITokenAcquisition>();
var graphClient = new GraphServiceClient(
new DelegateAuthenticationProvider(async (request) =>
{
var token = await tokenAcquisition
.GetAccessTokenForUserAsync(GraphConstants.Scopes, user: context.Principal);
request.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", token);
})
);
// Get user information from Graph
try
{
var user = await graphClient.Me.Request()
.Select(u => new
{
u.DisplayName,
u.Mail,
u.UserPrincipalName,
u.MailboxSettings
})
.GetAsync();
context.Principal.AddUserGraphInfo(user);
}
catch (ServiceException)
{
}
// Get the user's photo
// If the user doesn't have a photo, this throws
try
{
var photo = await graphClient.Me
.Photos["48x48"]
.Content
.Request()
.GetAsync();
context.Principal.AddUserGraphPhoto(photo);
}
catch (ServiceException ex)
{
if (ex.IsMatch("ErrorItemNotFound") ||
ex.IsMatch("ConsumerPhotoIsNotSupported"))
{
context.Principal.AddUserGraphPhoto(null);
}
}
};
options.Events.OnAuthenticationFailed = context =>
{
var error = WebUtility.UrlEncode(context.Exception.Message);
context.Response
.Redirect($"/Home/ErrorWithMessage?message=Authentication+error&debug={error}");
context.HandleResponse();
return Task.FromResult(0);
};
options.Events.OnRemoteFailure = context =>
{
if (context.Failure is OpenIdConnectProtocolException)
{
var error = WebUtility.UrlEncode(context.Failure.Message);
context.Response
.Redirect($"/Home/ErrorWithMessage?message=Sign+in+error&debug={error}");
context.HandleResponse();
}
return Task.FromResult(0);
};
})
// Add ability to call web API (Graph)
// and get access tokens
.EnableTokenAcquisitionToCallDownstreamApi(options =>
{
Configuration.Bind("AzureAd", options);
}, GraphConstants.Scopes)
// Add a GraphServiceClient via dependency injection
.AddMicrosoftGraph(options =>
{
options.Scopes = string.Join(' ', GraphConstants.Scopes);
})
// Use in-memory token cache
// See https://github.com/AzureAD/microsoft-identity-web/wiki/token-cache-serialization
.AddInMemoryTokenCaches();
Since you are using MVC, I recommend using the ProxyProvider over the Simple Provider.
SimpleProvider - useful when you have existing authentication on the client side (such as Msal.js)
ProxyProvider - useful when you are authenticating on the backend and all graph calls are proxied from the client to your backend.
This .NET core MVC sample might help - it is using the ProxyProvider with the components
Finally, I have discovered how to do my last mile bridging for these two technology.
Following are the lines of the code that I have made the changes. Since I'm using new development method as oppose by MSAL.NET, a lot of implementation has been simplified, so many of examples or article out there, may not really able to use it directly.
Besides using links shared by #Nikola and me above, you also can try to use below
https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/master/
to consolidate to become your very own solution. Below are the changes I have made to make it worked.
Change in Startup.cs class
// Add application services. services.AddSingleton<IGraphAuthProvider, GraphAuthProvider>(); //services.AddSingleton<IGraphServiceClientFactory, GraphServiceClientFactory>();
Change in ProxyController.cs class
private readonly GraphServiceClient _graphClient;
public ProxyController(IWebHostEnvironment hostingEnvironment, GraphServiceClient graphclient)
{
_env = hostingEnvironment;
//_graphServiceClientFactory = graphServiceClientFactory;
_graphClient = graphclient;
}
Change in ProcessRequestAsync method under ProxyController.cs
//var graphClient = _graphServiceClientFactory.GetAuthenticatedGraphClient((ClaimsIdentity)User.Identity);
var qs = HttpContext.Request.QueryString;
var url = $"{GetBaseUrlWithoutVersion(_graphClient)}/{all}{qs.ToUriComponent()}";
var request = new BaseRequest(url, _graphClient, null)
{
Method = method,
ContentType = HttpContext.Request.ContentType,
};

why asp.net mvc does not include the image uploaded folder in the project?

what I have found that the images uploaded by my application are not included in the project and that I have to include them manually image by image so what is the correct way of asp.net mvc project to let the images uploaded to be included in the project.
The following code is the one that upload the images to the folder and creates a unique name for each image. but still those images are not included in the project explorer.
public ActionResult Create(Job job, HttpPostedFileBase JobImage)
{
var value = "999999999";
var result4 = from app in db.Job where app.UniqueJobImageName.Contains(value) select app;
if(result4.FirstOrDefault() != null)
{
value = generateRandom();
}
if (ModelState.IsValid && CheckFileType(JobImage.FileName))
{
string ext = Path.GetExtension(JobImage.FileName);
var fileName = Path.GetFileName(JobImage.FileName);
job.JobImage = JobImage.FileName;
job.UniqueJobImageName = value + ext;
var path = Path.Combine(Server.MapPath("~/Images"), value + ext);
JobImage.SaveAs(path);
job.UserId = User.Identity.GetUserId();
job.jobUrl = "";
job.Month = DateTime.Now.ToString("MMMM");
job.DateAndTime = DateTime.Now;
AllJobModel all = new AllJobModel
{
JobTitle = job.JobTitle,
JobDescription = job.JobDescription,
JobImage = job.JobImage,
UniqueJobImageName = job.UniqueJobImageName,
locationName = job.locationName,
minimumSalary = job.minimumSalary.ToString(),
maximumSalary = job.maximumSalary.ToString(),
jobUrl = job.jobUrl,
PostedDate = DateTime.Now.ToString("dd/MM/yyyy"),
UserId= User.Identity.GetUserId(),
};
db.AllJobModel.Add(all);
db.SaveChanges();
db.Job.Add(job);
db.SaveChanges();
return RedirectToAction("Index","Home");
}else if (!CheckFileType(JobImage.FileName))
{
}
return View(job);
}
enter image description here
This doesn't make any sense. The uploaded images are content created by the user. They are not a deployable component of the site (or, they shouldn't be anyway). They are user-generated content, not developer resources.
If you are looking to effectively migrate your data (i.e. copy database entries and other user-generated content such as image files) from one environment to another, then that is a separate task for which you can create a separate process and/or automated script. Don't confuse it with the job of uploading a new version of your application code.
P.S. Even if what you were asking for was a sensible goal, it's impossible anyway - the executable version of your code is not the same as the code you see in Visual Studio in your project. In a modern ASP.NET application the executable code is in a different folder (even when you're running in debug mode in Visual Studio) and it has no concept or knowledge of the original project it was compiled from, or where to find it, or how to interact with it.

Modified Web.Config using visual studio or powershell to specific web application

I have a problem in modifying web.config to specific web application
I've search and try so many solution, when i deploy, the modification still affect to all existing web application
here is my code part of my code :
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWebService service = SPWebService.ContentService;
SPWebConfigModification myModification = new SPWebConfigModification();
SPSite site = new SPSite("http://win-a52s8epvot4:888/");
SPWeb web = site.OpenWeb();
myModification.Path = "configuration/appSettings";
myModification.Name = "add[#key='SQLArchiveConnectionString'][#value='Data Source=WIN-A52S8EPVOT4;Initial Catalog=TRAEmployee;User ID=sa;Password=P#ssw0rd;Persist Security Info=False;']";
myModification.Sequence = 0;
myModification.Owner = "administrator";
myModification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
myModification.Value = "<add key='SQLArchiveConnectionString' value='Data Source=WIN-A52S8EPVOT4;Initial Catalog=TRAEmployee;User ID=sa;Password=P#ssw0rd;Persist Security Info=False;' />";
web.Site.WebApplication.WebConfigModifications.Add(myModification);
service.Update();
service.ApplyWebConfigModifications();
}
is there any suggestion for my problem
your reply will greatly help me to finish this problem
Regards,
Jay

EntityClassGenerator : Not generating any output for NorthwindDataService

I am trying to generate the OData Proxy for the service : http://services.odata.org/Northwind/Northwind.svc/$metadata
I am using System.Data.Services.Design.EntityClassGenerator for generating the OData proxy.
When I instantiate the EntityClassGenerator and call GenerateCode the output has no errors. But there is no code in the generated proxy code.
The same code works for my own service. But when I point it to any external service the EntityClassGenerator is not working.
Here is the code :
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(metadataEndpoint);
webRequest.Method = "GET";
webRequest.ContentType = "text/xml;encoding='utf-8";
webRequest.Proxy = (proxy != null) ? proxy : WebRequest.DefaultWebProxy;
using (WebResponse response = webRequest.GetResponse())
{
string xml = string.Empty;
XmlReaderSettings settings = new XmlReaderSettings();
using (TextReader reader = new StreamReader(response.GetResponseStream()))
{
xml = reader.ReadToEnd();
using (XmlTextReader sourceReader = new XmlTextReader(reader))
{
using (StringWriter targetWriter = new StringWriter())
{
// Generate the OData End point proxy.
EntityClassGenerator entityGenerator = new EntityClassGenerator(LanguageOption.GenerateCSharpCode);
entityGenerator.OnPropertyGenerated += new EventHandler<PropertyGeneratedEventArgs>(entityGenerator_OnPropertyGenerated);
IList<System.Data.Metadata.Edm.EdmSchemaError> errors = entityGenerator.GenerateCode(sourceReader, targetWriter, namespacename);
entityGenerator.OnPropertyGenerated -= new EventHandler<PropertyGeneratedEventArgs>(entityGenerator_OnPropertyGenerated);
odataProxyCode = targetWriter.ToString();
}
}
}
}
I found the code in the question to be a useful starting point for doing exactly what the OP was asking. So even though the OP doesn't accept answers, I'll describe the changes I made to get it to work in case it is useful to someone else.
Removed the xml = reader.ReadToEnd(); call. I assume that was for debugging purposes to look at the response from the web request, but it had the result of "emptying" the reader object of the response. That meant that there was nothing left in the reader for the GenerateCode call.
The important one: Changed the use of EntityClassGenerator to System.Data.Services.Design.EntityClassGenerator. In the code below, I included the entire name space for clarity and specificity. Based on the code in the question, it appears the OP was probably using System.Data.Entity.Design.EntityClassGenerator. I used .NET Reflector to examine datasvcutil.exe, which is a command-line utility that can generate the proxy classes. I saw that it referenced the generator in that other name space.
For figuring out the problems, I dumped the errors from the GenerateCode call. One could examine them in the debugger, but some kind of automated checking of them would be needed regardless.
Here is what I ended up with:
HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.
Create("http://services.odata.org/Northwind/Northwind.svc/$metadata");
webRequest.Method = "GET";
webRequest.ContentType = "text/xml;encoding='utf-8";
webRequest.Proxy = WebRequest.DefaultWebProxy;
using (WebResponse response = webRequest.GetResponse())
{
using (TextReader reader = new StreamReader(response.GetResponseStream()))
{
using (XmlTextReader sourceReader = new XmlTextReader(reader))
{
using (StringWriter targetWriter = new StringWriter())
{
// Generate the OData End point proxy.
System.Data.Services.Design.EntityClassGenerator entityGenerator =
new System.Data.Services.Design.EntityClassGenerator(
System.Data.Services.Design.LanguageOption.GenerateCSharpCode);
IList<System.Data.Metadata.Edm.EdmSchemaError> errors =
entityGenerator.GenerateCode(sourceReader, targetWriter,
"My.Model.Entities");
foreach (System.Data.Metadata.Edm.EdmSchemaError error in errors)
Console.WriteLine("{0}: {1}", error.Severity.ToString(), error.Message);
string odataProxyCode = targetWriter.ToString();
}
}
}
}

Problem adding a dynamic field to a SPList in sharepoint

We have the following code in a webpart:
using (SPSite site = new SPSite("http://localhost/"))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.SiteUserInfoList;
if (!list.Fields.ContainsField("Office"))
{
list.Fields.Add("Office", SPFieldType.Text, false);
list.Update();
}
}
}
in the 4th line where we add a item to the list we get this error: "Updates are currently disallowed on GET requests. To allow updates on a GET, set the 'AllowUnsafeUpdates' property on SPWeb".
Then we added this line before adding the item to the list:
web.AllowUnsafeUpdates = true;
Now we are getting this error:
"You are currently signed in as: [domain]\username".
Sign in as a different user.
The account that we are using have administrative access too.
Any idea how we can get the following code executing:
web.AllowUnsafeUpdates = true;
list.Fields.Add("Office", SPFieldType.Text, false);
list.Update();
Got it working the following way:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite(web.Site.ID))
{
using (SPWeb web = site.OpenWeb())
{
SPList list = web.SiteUserInfoList;
if (!list.Fields.ContainsField("Office"))
{
list.Fields.Add("Office", SPFieldType.Text, false);
list.Update();
}
}
}
});
Needed to run the codes with Full Control rights :)
But we shouldn't be writings all the cods this way.

Resources